xref: /FreeRTOS-Plus-TCP-v4.0.0/source/include/FreeRTOS_Routing.h (revision df5aed9e58a72e2489b6c1936788885672c62981)
1 /*
2  * FreeRTOS+TCP V2.3.1
3  * Copyright (C) 2020 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of
6  * this software and associated documentation files (the "Software"), to deal in
7  * the Software without restriction, including without limitation the rights to
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9  * the Software, and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  *
22  * http://aws.amazon.com/freertos
23  * http://www.FreeRTOS.org
24  */
25 
26 #ifndef FREERTOS_ROUTING_H
27     #define FREERTOS_ROUTING_H
28 
29     #include "FreeRTOS.h"
30     #include "FreeRTOS_IP.h"
31 
32     #if ( ipconfigUSE_DHCP != 0 )
33         #include "FreeRTOS_DHCP.h"
34     #endif
35 
36     #if ( ipconfigUSE_IPv6 != 0 )
37         #include "FreeRTOS_DHCPv6.h"
38     #endif
39 
40     #ifdef __cplusplus
41         extern "C" {
42     #endif
43 
44 /* Every NetworkInterface needs a set of access functions: */
45 
46 /* Initialise the interface. */
47     typedef BaseType_t ( * NetworkInterfaceInitialiseFunction_t ) ( struct xNetworkInterface * pxDescriptor );
48 
49 /* Send out an Ethernet packet. */
50     typedef BaseType_t ( * NetworkInterfaceOutputFunction_t ) ( struct xNetworkInterface * pxDescriptor,
51                                                                 NetworkBufferDescriptor_t * const pxNetworkBuffer,
52                                                                 BaseType_t xReleaseAfterSend );
53 
54 /* Return true as long as the LinkStatus on the PHY is present. */
55     typedef BaseType_t ( * GetPhyLinkStatusFunction_t ) ( struct xNetworkInterface * pxDescriptor );
56 
57 /** @brief These NetworkInterface access functions are collected in a struct: */
58     typedef struct xNetworkInterface
59     {
60         const char * pcName;                               /**< Just for logging, debugging. */
61         void * pvArgument;                                 /**< Will be passed to the access functions. */
62         NetworkInterfaceInitialiseFunction_t pfInitialise; /**< This function will be called upon initialisation and repeated until it returns pdPASS. */
63         NetworkInterfaceOutputFunction_t pfOutput;         /**< This function is supposed to send out a packet. */
64         GetPhyLinkStatusFunction_t pfGetPhyLinkStatus;     /**< This function will return pdTRUE as long as the PHY Link Status is high. */
65         struct
66         {
67             uint32_t
68                 bInterfaceUp : 1,             /**< Non-zero as soon as the interface is up. */
69                 bCallDownEvent : 1;           /**< The down-event must be called. */
70         } bits;                               /**< A collection of boolean flags. */
71 
72         struct xNetworkEndPoint * pxEndPoint; /**< A list of end-points bound to this interface. */
73         struct xNetworkInterface * pxNext;    /**< The next interface in a linked list. */
74     } NetworkInterface_t;
75 
76 /*
77  *  // As an example:
78  *  NetworkInterface_t xZynqDescriptor = {
79  *      .pcName					= "Zynq-GEM",
80  *      .pvArgument				= ( void * )1,
81  *      .pfInitialise           = xZynqGEMInitialise,
82  *      .pfOutput               = xZynqGEMOutput,
83  *      .pfGetPhyLinkStatus     = xZynqGEMGetPhyLinkStatus,
84  *  };
85  */
86 
87 /** @brief The network settings for IPv4. */
88     typedef struct xIPV4Parameters
89     {
90         uint32_t ulIPAddress;                                                /**< The actual IPv4 address. Will be 0 as long as end-point is still down. */
91         uint32_t ulNetMask;                                                  /**< The netmask. */
92         uint32_t ulGatewayAddress;                                           /**< The IP-address of the gateway. */
93         uint32_t ulDNSServerAddresses[ ipconfigENDPOINT_DNS_ADDRESS_COUNT ]; /**< IP-addresses of DNS servers. */
94         uint32_t ulBroadcastAddress;                                         /**< The local broadcast address, e.g. '192.168.1.255'. */
95         uint8_t ucDNSIndex;                                                  /**< The index of the next DNS address to be used. */
96     } IPV4Parameters_t;
97 
98     #if ( ipconfigUSE_IPv6 != 0 )
99         typedef struct xIPV6Parameters
100         {
101             IPv6_Address_t xIPAddress;      /* The actual IPv4 address. Will be 0 as long as end-point is still down. */
102             size_t uxPrefixLength;          /* Number of valid bytes in the network prefix. */
103             IPv6_Address_t xPrefix;         /* The network prefix, e.g. fe80::/10 */
104             IPv6_Address_t xGatewayAddress; /* Gateway to the web. */
105             IPv6_Address_t xDNSServerAddresses[ ipconfigENDPOINT_DNS_ADDRESS_COUNT ];
106             uint8_t ucDNSIndex;             /**< The index of the next DNS address to be used. */
107         } IPV6Parameters_t;
108     #endif
109 
110     #if ( ipconfigUSE_RA != 0 )
111 /* Router Advertisement (RA). End-points can obtain their IP-address by asking for a RA. */
112         typedef enum xRAState
113         {
114             eRAStateApply,    /* Send a Router Solicitation. */
115             eRAStateWait,     /* Wait for a Router Advertisement. */
116             eRAStateIPTest,   /* Take a random IP address, test if another device is using it already. */
117             eRAStateIPWait,   /* Wait for a reply, if any */
118             eRAStatePreLease, /* The device is ready to go to the 'eRAStateLease' state. */
119             eRAStateLease,    /* The device is up, repeat the RA-process when timer expires. */
120             eRAStateFailed,
121         } eRAState_t;
122 
123         struct xRA_DATA
124         {
125             struct
126             {
127                 uint32_t
128                     bRouterReplied : 1,
129                     bIPAddressInUse : 1;
130             }
131             bits;
132             TickType_t ulPreferredLifeTime;
133             UBaseType_t uxRetryCount;
134             /* Maintains the RA state machine state. */
135             eRAState_t eRAState;
136         };
137 
138         typedef struct xRA_DATA RAData_t;
139     #endif /* ( ipconfigUSE_RA != 0 ) */
140 
141 /** @brief The description of an end-point. */
142     typedef struct xNetworkEndPoint
143     {
144         union
145         {
146             struct
147             {
148                 IPV4Parameters_t ipv4_settings; /**< Actual IPv4 settings used by the end-point. */
149                 IPV4Parameters_t ipv4_defaults; /**< Use values form "ipv4_defaults" in case DHCP has failed. */
150             };
151             #if ( ipconfigUSE_IPv6 != 0 )
152                 struct
153                 {
154                     IPV6Parameters_t ipv6_settings; /**< Actual IPv6 settings used by the end-point. */
155                     IPV6Parameters_t ipv6_defaults; /**< Use values form "ipv6_defaults" in case DHCP has failed. */
156                 };
157             #endif
158         };
159         MACAddress_t xMACAddress; /**< The MAC-address assigned to this end-point. */
160         struct
161         {
162             uint32_t
163                 bIsDefault : 1, /**< This bit will be removed. */
164             #if ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_DHCPv6 != 0 )
165                 bWantDHCP : 1,  /**< This end-point wants to use DHCPv4 to obtain an IP-address. */
166             #endif /* ipconfigUSE_DHCP */
167             #if ( ipconfigUSE_RA != 0 )
168                 bWantRA : 1,         /**< This end-point wants to use RA/SLAAC to obtain an IP-address. */
169             #endif /* ipconfigUSE_RA */
170             bIPv6 : 1,               /**< This end-point has an IP-address of type IPv6. */
171             #if ( ipconfigUSE_NETWORK_EVENT_HOOK != 0 )
172                 bCallDownHook : 1,   /**< The network down hook-must be called for this end-point. */
173             #endif /* ipconfigUSE_NETWORK_EVENT_HOOK */
174             bEndPointUp : 1;         /**< The end-point is up. */
175         } bits;                      /**< A collection of boolean properties. */
176         uint8_t usDNSType;           /**< A LLMNR/mDNS lookup is being done for an IPv6 address.
177                                       * This field is only valid while xApplicationDNSQueryHook() is called. */
178         #if ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_RA != 0 )
179             IPTimer_t xDHCP_RATimer; /**<  The timer used to call the DHCP/DHCPv6/RA state machine. */
180         #endif /* ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_RA != 0 ) */
181         #if ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_DHCPv6 != 0 )
182             DHCPData_t xDHCPData; /**< A description of the DHCP client state machine. */
183         #endif /* ( ipconfigUSE_DHCP != 0 ) || ( ipconfigUSE_DHCPv6 != 0 ) */
184         #if ( ipconfigUSE_IPv6 != 0 )
185             DHCPMessage_IPv6_t * pxDHCPMessage; /**< A description of the DHCPv6 client state machine. */
186         #endif
187         #if ( ipconfigUSE_RA != 0 )
188             RAData_t xRAData;                    /**< A description of the Router Advertisement ( RA ) client state machine. */
189         #endif /* ( ipconfigUSE_RA != 0 ) */
190         NetworkInterface_t * pxNetworkInterface; /**< The network interface that owns this end-point. */
191         struct xNetworkEndPoint * pxNext;        /**< The next end-point in the chain. */
192     } NetworkEndPoint_t;
193 
194     #define END_POINT_USES_DHCP( pxEndPoint )    ( ( pxEndPoint )->bits.bWantDHCP != pdFALSE_UNSIGNED )
195     #define END_POINT_USES_RA( pxEndPoint )      ( ( ( pxEndPoint )->bits.bIPv6 != pdFALSE_UNSIGNED ) && ( ( pxEndPoint )->bits.bWantRA != pdFALSE_UNSIGNED ) )
196 
197     #define ENDPOINT_IS_IPv4( pxEndPoint )       ( ( ( pxEndPoint ) != NULL ) && ( ( pxEndPoint )->bits.bIPv6 == 0U ) )
198     #define ENDPOINT_IS_IPv6( pxEndPoint )       ( ( ( pxEndPoint ) != NULL ) && ( ( pxEndPoint )->bits.bIPv6 != 0U ) )
199 
200 
201 /*
202  * Add a new physical Network Interface.  The object pointed to by 'pxInterface'
203  * must continue to exist.
204  * Only the Network Interface function xx_FillInterfaceDescriptor() shall call this function.
205  */
206     NetworkInterface_t * FreeRTOS_AddNetworkInterface( NetworkInterface_t * pxInterface );
207 
208 /*
209  * Get the first Network Interface.
210  */
211     NetworkInterface_t * FreeRTOS_FirstNetworkInterface( void );
212 
213 /*
214  * Get the next Network Interface.
215  */
216     NetworkInterface_t * FreeRTOS_NextNetworkInterface( const NetworkInterface_t * pxInterface );
217 
218 /*
219  * Get the first end-point belonging to a given interface.  When pxInterface is
220  * NULL, the very first end-point will be returned.
221  */
222     NetworkEndPoint_t * FreeRTOS_FirstEndPoint( const NetworkInterface_t * pxInterface );
223 
224 /*
225  * Get the next end-point.  When pxInterface is null, all end-points can be
226  * iterated.
227  */
228     NetworkEndPoint_t * FreeRTOS_NextEndPoint( const NetworkInterface_t * pxInterface,
229                                                NetworkEndPoint_t * pxEndPoint );
230 
231 /*
232  * Find the end-point with given IP-address.
233  */
234     NetworkEndPoint_t * FreeRTOS_FindEndPointOnIP_IPv4( uint32_t ulIPAddress,
235                                                         uint32_t ulWhere );
236 
237     #if ( ipconfigUSE_IPv6 != 0 )
238         /* Find the end-point with given IP-address. */
239         NetworkEndPoint_t * FreeRTOS_FindEndPointOnIP_IPv6( const IPv6_Address_t * pxIPAddress );
240     #endif /* ipconfigUSE_IPv6 */
241 
242 /*
243  * Find the end-point with given MAC-address.
244  * The search can be limited by supplying a particular interface.
245  */
246     NetworkEndPoint_t * FreeRTOS_FindEndPointOnMAC( const MACAddress_t * pxMACAddress,
247                                                     const NetworkInterface_t * pxInterface );
248 
249 /*
250  * Find the best fitting end-point to reach a given IP-address.
251  * Find an end-point whose IP-address is in the same network as the IP-address provided.
252  * 'ulWhere' is temporary and or debugging only.
253  */
254     NetworkEndPoint_t * FreeRTOS_FindEndPointOnNetMask( uint32_t ulIPAddress,
255                                                         uint32_t ulWhere );
256 
257 /*
258  * Find the best fitting end-point to reach a given IP-address on a given interface
259  * 'ulWhere' is temporary and or debugging only.
260  */
261     NetworkEndPoint_t * FreeRTOS_InterfaceEndPointOnNetMask( const NetworkInterface_t * pxInterface,
262                                                              uint32_t ulIPAddress,
263                                                              uint32_t ulWhere );
264 
265     #if ( ipconfigUSE_IPv6 != 0 )
266         NetworkEndPoint_t * FreeRTOS_FindEndPointOnNetMask_IPv6( const IPv6_Address_t * pxIPv6Address );
267     #endif /* ipconfigUSE_IPv6 */
268 
269     #if ( ipconfigUSE_IPv6 != 0 )
270 
271 /* Get the first end-point belonging to a given interface.
272  * When pxInterface is NULL, the very first end-point will be returned. */
273         NetworkEndPoint_t * FreeRTOS_FirstEndPoint_IPv6( const NetworkInterface_t * pxInterface );
274     #endif /* ipconfigUSE_IPv6 */
275 
276 /* A ethernet packet has come in on a certain network interface.
277  * Find the best matching end-point. */
278     NetworkEndPoint_t * FreeRTOS_MatchingEndpoint( const NetworkInterface_t * pxNetworkInterface,
279                                                    const uint8_t * pucEthernetBuffer );
280 
281 /* Find an end-point that has a defined gateway.
282  * xIPType should equal ipTYPE_IPv4 or ipTYPE_IPv6. */
283     NetworkEndPoint_t * FreeRTOS_FindGateWay( BaseType_t xIPType );
284 
285 /* Fill-in the end-point structure. */
286     void FreeRTOS_FillEndPoint( NetworkInterface_t * pxNetworkInterface,
287                                 NetworkEndPoint_t * pxEndPoint,
288                                 const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
289                                 const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ],
290                                 const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
291                                 const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ],
292                                 const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );
293 
294     #if ( ipconfigUSE_IPv6 != 0 )
295         /* Fill-in the end-point structure. */
296         void FreeRTOS_FillEndPoint_IPv6( NetworkInterface_t * pxNetworkInterface,
297                                          NetworkEndPoint_t * pxEndPoint,
298                                          const IPv6_Address_t * pxIPAddress,
299                                          const IPv6_Address_t * pxNetPrefix,
300                                          size_t uxPrefixLength,
301                                          const IPv6_Address_t * pxGatewayAddress,
302                                          const IPv6_Address_t * pxDNSServerAddress, /* Not used yet. */
303                                          const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] );
304     #endif
305 
306     #if ( ipconfigHAS_ROUTING_STATISTICS == 1 )
307 /** @brief Some simple network statistics. */
308         typedef struct xRoutingStats
309         {
310             UBaseType_t ulOnIp;             /**< The number of times 'FreeRTOS_FindEndPointOnIP_IPv4()' has been called. */
311             UBaseType_t ulOnMAC;            /**< The number of times 'FreeRTOS_FindEndPointOnMAC()' has been called. */
312             UBaseType_t ulOnNetMask;        /**< The number of times 'FreeRTOS_InterfaceEndPointOnNetMask()' has been called. */
313             UBaseType_t ulMatching;         /**< The number of times 'FreeRTOS_MatchingEndpoint()' has been called. */
314             UBaseType_t ulLocations[ 14 ];  /**< The number of times 'FreeRTOS_InterfaceEndPointOnNetMask()' has been called from a particular location. */
315             UBaseType_t ulLocationsIP[ 8 ]; /**< The number of times 'FreeRTOS_FindEndPointOnIP_IPv4()' has been called from a particular location. */
316         } RoutingStats_t;
317 
318         extern RoutingStats_t xRoutingStatistics;
319     #endif /* ( ipconfigHAS_ROUTING_STATISTICS == 1 ) */
320 
321     NetworkEndPoint_t * pxGetSocketEndpoint( ConstSocket_t xSocket );
322     void vSetSocketEndpoint( Socket_t xSocket,
323                              NetworkEndPoint_t * pxEndPoint );
324 
325     const char * pcEndpointName( const NetworkEndPoint_t * pxEndPoint,
326                                  char * pcBuffer,
327                                  size_t uxSize );
328 
329     typedef enum
330     {
331         eIPv6_Global,    /* 001           */
332         eIPv6_LinkLocal, /* 1111 1110 10  */
333         eIPv6_SiteLocal, /* 1111 1110 11  */
334         eIPv6_Multicast, /* 1111 1111     */
335         eIPv6_Unknown,   /* Not implemented. */
336     }
337     IPv6_Type_t;
338 
339 /**
340  * @brief Check the type of an IPv16 address.
341  *
342  * @return A value from enum IPv6_Type_t.
343  */
344     IPv6_Type_t xIPv6_GetIPType( const IPv6_Address_t * pxAddress );
345 
346     #ifdef __cplusplus
347 }         /* extern "C" */
348     #endif
349 
350 #endif /* FREERTOS_ROUTING_H */
351