2 * FreeRTOS+TCP V2.0.7
\r
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
\r
6 * this software and associated documentation files (the "Software"), to deal in
\r
7 * the Software without restriction, including without limitation the rights to
\r
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
\r
9 * the Software, and to permit persons to whom the Software is furnished to do so,
\r
10 * subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in all
\r
13 * copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
\r
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
\r
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
\r
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\r
22 * http://aws.amazon.com/freertos
\r
23 * http://www.FreeRTOS.org
\r
26 /* Standard includes. */
\r
31 /* FreeRTOS includes. */
\r
32 #include "FreeRTOS.h"
\r
37 /* FreeRTOS+TCP includes. */
\r
38 #include "FreeRTOS_IP.h"
\r
39 #include "FreeRTOS_Sockets.h"
\r
40 #include "FreeRTOS_IP_Private.h"
\r
41 #include "FreeRTOS_ARP.h"
\r
42 #include "FreeRTOS_UDP_IP.h"
\r
43 #include "FreeRTOS_TCP_IP.h"
\r
44 #include "FreeRTOS_DHCP.h"
\r
45 #include "NetworkInterface.h"
\r
46 #include "NetworkBufferManagement.h"
\r
47 #include "FreeRTOS_DNS.h"
\r
50 /* Used to ensure the structure packing is having the desired effect. The
\r
51 'volatile' is used to prevent compiler warnings about comparing a constant with
\r
53 #define ipEXPECTED_EthernetHeader_t_SIZE ( ( size_t ) 14 )
\r
54 #define ipEXPECTED_ARPHeader_t_SIZE ( ( size_t ) 28 )
\r
55 #define ipEXPECTED_IPHeader_t_SIZE ( ( size_t ) 20 )
\r
56 #define ipEXPECTED_IGMPHeader__SIZE ( ( size_t ) 8 )
\r
57 #define ipEXPECTED_ICMPHeader_t_SIZE ( ( size_t ) 8 )
\r
58 #define ipEXPECTED_UDPHeader_t_SIZE ( ( size_t ) 8 )
\r
59 #define ipEXPECTED_TCPHeader_t_SIZE ( ( size_t ) 20 )
\r
62 /* ICMP protocol definitions. */
\r
63 #define ipICMP_ECHO_REQUEST ( ( uint8_t ) 8 )
\r
64 #define ipICMP_ECHO_REPLY ( ( uint8_t ) 0 )
\r
67 /* Time delay between repeated attempts to initialise the network hardware. */
\r
68 #define ipINITIALISATION_RETRY_DELAY ( pdMS_TO_TICKS( 3000 ) )
\r
70 /* Defines how often the ARP timer callback function is executed. The time is
\r
71 shorted in the Windows simulator as simulated time is not real time. */
\r
72 #ifndef ipARP_TIMER_PERIOD_MS
\r
74 #define ipARP_TIMER_PERIOD_MS ( 500 ) /* For windows simulator builds. */
\r
76 #define ipARP_TIMER_PERIOD_MS ( 10000 )
\r
80 #ifndef iptraceIP_TASK_STARTING
\r
81 #define iptraceIP_TASK_STARTING() do {} while( 0 )
\r
84 #if( ( ipconfigUSE_TCP == 1 ) && !defined( ipTCP_TIMER_PERIOD_MS ) )
\r
85 /* When initialising the TCP timer,
\r
86 give it an initial time-out of 1 second. */
\r
87 #define ipTCP_TIMER_PERIOD_MS ( 1000 )
\r
90 /* If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 1, then the Ethernet
\r
91 driver will filter incoming packets and only pass the stack those packets it
\r
92 considers need processing. In this case ipCONSIDER_FRAME_FOR_PROCESSING() can
\r
93 be #defined away. If ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES is set to 0
\r
94 then the Ethernet driver will pass all received packets to the stack, and the
\r
95 stack must do the filtering itself. In this case ipCONSIDER_FRAME_FOR_PROCESSING
\r
96 needs to call eConsiderFrameForProcessing. */
\r
97 #if ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES == 0
\r
98 #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eConsiderFrameForProcessing( ( pucEthernetBuffer ) )
\r
100 #define ipCONSIDER_FRAME_FOR_PROCESSING( pucEthernetBuffer ) eProcessBuffer
\r
103 /* The character used to fill ICMP echo requests, and therefore also the
\r
104 character expected to fill ICMP echo replies. */
\r
105 #define ipECHO_DATA_FILL_BYTE 'x'
\r
107 #if( ipconfigBYTE_ORDER == pdFREERTOS_LITTLE_ENDIAN )
\r
108 /* The bits in the two byte IP header field that make up the fragment offset value. */
\r
109 #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0xff0f )
\r
111 /* The bits in the two byte IP header field that make up the fragment offset value. */
\r
112 #define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff )
\r
113 #endif /* ipconfigBYTE_ORDER */
\r
115 /* The maximum time the IP task is allowed to remain in the Blocked state if no
\r
116 events are posted to the network event queue. */
\r
117 #ifndef ipconfigMAX_IP_TASK_SLEEP_TIME
\r
118 #define ipconfigMAX_IP_TASK_SLEEP_TIME ( pdMS_TO_TICKS( 10000UL ) )
\r
121 /* When a new TCP connection is established, the value of
\r
122 'ulNextInitialSequenceNumber' will be used as the initial sequence number. It
\r
123 is very important that at start-up, 'ulNextInitialSequenceNumber' contains a
\r
124 random value. Also its value must be increased continuously in time, to prevent
\r
125 a third party guessing the next sequence number and take-over a TCP connection.
\r
126 It is advised to increment it by 1 ever 4us, which makes about 256 times
\r
128 #define ipINITIAL_SEQUENCE_NUMBER_FACTOR 256UL
\r
130 /* Returned as the (invalid) checksum when the protocol being checked is not
\r
131 handled. The value is chosen simply to be easy to spot when debugging. */
\r
132 #define ipUNHANDLED_PROTOCOL 0x4321u
\r
134 /* Returned to indicate a valid checksum when the checksum does not need to be
\r
136 #define ipCORRECT_CRC 0xffffu
\r
138 /* Returned as the (invalid) checksum when the length of the data being checked
\r
139 had an invalid length. */
\r
140 #define ipINVALID_LENGTH 0x1234u
\r
142 /*-----------------------------------------------------------*/
\r
144 typedef struct xIP_TIMER
\r
147 bActive : 1, /* This timer is running and must be processed. */
\r
148 bExpired : 1; /* Timer has expired and a task must be processed. */
\r
149 TimeOut_t xTimeOut;
\r
150 TickType_t ulRemainingTime;
\r
151 TickType_t ulReloadTime;
\r
154 /* Used in checksum calculation. */
\r
155 typedef union _xUnion32
\r
162 /* Used in checksum calculation. */
\r
163 typedef union _xUnionPtr
\r
170 /*-----------------------------------------------------------*/
\r
173 * The main TCP/IP stack processing task. This task receives commands/events
\r
174 * from the network hardware drivers and tasks that are using sockets. It also
\r
175 * maintains a set of protocol timers.
\r
177 static void prvIPTask( void *pvParameters );
\r
180 * Called when new data is available from the network interface.
\r
182 static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer );
\r
185 * Process incoming IP packets.
\r
187 static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * const pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer );
\r
189 #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
\r
191 * Process incoming ICMP packets.
\r
193 static eFrameProcessingResult_t prvProcessICMPPacket( ICMPPacket_t * const pxICMPPacket );
\r
194 #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
\r
197 * Turns around an incoming ping request to convert it into a ping reply.
\r
199 #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 )
\r
200 static eFrameProcessingResult_t prvProcessICMPEchoRequest( ICMPPacket_t * const pxICMPPacket );
\r
201 #endif /* ipconfigREPLY_TO_INCOMING_PINGS */
\r
204 * Processes incoming ping replies. The application callback function
\r
205 * vApplicationPingReplyHook() is called with the results.
\r
207 #if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
\r
208 static void prvProcessICMPEchoReply( ICMPPacket_t * const pxICMPPacket );
\r
209 #endif /* ipconfigSUPPORT_OUTGOING_PINGS */
\r
212 * Called to create a network connection when the stack is first started, or
\r
213 * when the network connection is lost.
\r
215 static void prvProcessNetworkDownEvent( void );
\r
218 * Checks the ARP, DHCP and TCP timers to see if any periodic or timeout
\r
219 * processing is required.
\r
221 static void prvCheckNetworkTimers( void );
\r
224 * Determine how long the IP task can sleep for, which depends on when the next
\r
225 * periodic or timeout processing must be performed.
\r
227 static TickType_t prvCalculateSleepTime( void );
\r
230 * The network card driver has received a packet. In the case that it is part
\r
231 * of a linked packet chain, walk through it to handle every message.
\r
233 static void prvHandleEthernetPacket( NetworkBufferDescriptor_t *pxBuffer );
\r
236 * Utility functions for the light weight IP timers.
\r
238 static void prvIPTimerStart( IPTimer_t *pxTimer, TickType_t xTime );
\r
239 static BaseType_t prvIPTimerCheck( IPTimer_t *pxTimer );
\r
240 static void prvIPTimerReload( IPTimer_t *pxTimer, TickType_t xTime );
\r
242 static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,
\r
243 NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength );
\r
245 /*-----------------------------------------------------------*/
\r
247 /* The queue used to pass events into the IP-task for processing. */
\r
248 QueueHandle_t xNetworkEventQueue = NULL;
\r
250 /*_RB_ Requires comment. */
\r
251 uint16_t usPacketIdentifier = 0U;
\r
253 /* For convenience, a MAC address of all 0xffs is defined const for quick
\r
255 const MACAddress_t xBroadcastMACAddress = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
\r
257 /* Structure that stores the netmask, gateway address and DNS server addresses. */
\r
258 NetworkAddressingParameters_t xNetworkAddressing = { 0, 0, 0, 0, 0 };
\r
260 /* Default values for the above struct in case DHCP
\r
261 does not lead to a confirmed request. */
\r
262 NetworkAddressingParameters_t xDefaultAddressing = { 0, 0, 0, 0, 0 };
\r
264 /* Used to ensure network down events cannot be missed when they cannot be
\r
265 posted to the network event queue because the network event queue is already
\r
267 static BaseType_t xNetworkDownEventPending = pdFALSE;
\r
269 /* Stores the handle of the task that handles the stack. The handle is used
\r
270 (indirectly) by some utility function to determine if the utility function is
\r
271 being called by a task (in which case it is ok to block) or by the IP task
\r
272 itself (in which case it is not ok to block). */
\r
273 static TaskHandle_t xIPTaskHandle = NULL;
\r
275 #if( ipconfigUSE_TCP != 0 )
\r
276 /* Set to a non-zero value if one or more TCP message have been processed
\r
277 within the last round. */
\r
278 static BaseType_t xProcessedTCPMessage;
\r
281 /* Simple set to pdTRUE or pdFALSE depending on whether the network is up or
\r
282 down (connected, not connected) respectively. */
\r
283 static BaseType_t xNetworkUp = pdFALSE;
\r
286 A timer for each of the following processes, all of which need attention on a
\r
288 1. ARP, to check its table entries
\r
289 2. DPHC, to send requests and to renew a reservation
\r
290 3. TCP, to check for timeouts, resends
\r
291 4. DNS, to check for timeouts when looking-up a domain.
\r
293 static IPTimer_t xARPTimer;
\r
294 #if( ipconfigUSE_DHCP != 0 )
\r
295 static IPTimer_t xDHCPTimer;
\r
297 #if( ipconfigUSE_TCP != 0 )
\r
298 static IPTimer_t xTCPTimer;
\r
300 #if( ipconfigDNS_USE_CALLBACKS != 0 )
\r
301 static IPTimer_t xDNSTimer;
\r
304 /* Set to pdTRUE when the IP task is ready to start processing packets. */
\r
305 static BaseType_t xIPTaskInitialised = pdFALSE;
\r
307 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
\r
308 /* Keep track of the lowest amount of space in 'xNetworkEventQueue'. */
\r
309 static UBaseType_t uxQueueMinimumSpace = ipconfigEVENT_QUEUE_LENGTH;
\r
312 /*-----------------------------------------------------------*/
\r
314 static void prvIPTask( void *pvParameters )
\r
316 IPStackEvent_t xReceivedEvent;
\r
317 TickType_t xNextIPSleep;
\r
318 FreeRTOS_Socket_t *pxSocket;
\r
319 struct freertos_sockaddr xAddress;
\r
321 /* Just to prevent compiler warnings about unused parameters. */
\r
322 ( void ) pvParameters;
\r
324 /* A possibility to set some additional task properties. */
\r
325 iptraceIP_TASK_STARTING();
\r
327 /* Generate a dummy message to say that the network connection has gone
\r
328 down. This will cause this task to initialise the network interface. After
\r
329 this it is the responsibility of the network interface hardware driver to
\r
330 send this message if a previously connected network is disconnected. */
\r
331 FreeRTOS_NetworkDown();
\r
333 #if( ipconfigUSE_TCP == 1 )
\r
335 /* Initialise the TCP timer. */
\r
336 prvIPTimerReload( &xTCPTimer, pdMS_TO_TICKS( ipTCP_TIMER_PERIOD_MS ) );
\r
340 /* Initialisation is complete and events can now be processed. */
\r
341 xIPTaskInitialised = pdTRUE;
\r
343 FreeRTOS_debug_printf( ( "prvIPTask started\n" ) );
\r
345 /* Loop, processing IP events. */
\r
348 ipconfigWATCHDOG_TIMER();
\r
350 /* Check the ARP, DHCP and TCP timers to see if there is any periodic
\r
351 or timeout processing to perform. */
\r
352 prvCheckNetworkTimers();
\r
354 /* Calculate the acceptable maximum sleep time. */
\r
355 xNextIPSleep = prvCalculateSleepTime();
\r
357 /* Wait until there is something to do. If the following call exits
\r
358 * due to a time out rather than a message being received, set a
\r
359 * 'NoEvent' value. */
\r
360 if ( xQueueReceive( xNetworkEventQueue, ( void * ) &xReceivedEvent, xNextIPSleep ) == pdFALSE ) {
\r
361 xReceivedEvent.eEventType = eNoEvent;
\r
364 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
\r
366 if( xReceivedEvent.eEventType != eNoEvent )
\r
368 UBaseType_t uxCount;
\r
370 uxCount = uxQueueSpacesAvailable( xNetworkEventQueue );
\r
371 if( uxQueueMinimumSpace > uxCount )
\r
373 uxQueueMinimumSpace = uxCount;
\r
377 #endif /* ipconfigCHECK_IP_QUEUE_SPACE */
\r
379 iptraceNETWORK_EVENT_RECEIVED( xReceivedEvent.eEventType );
\r
381 switch( xReceivedEvent.eEventType )
\r
383 case eNetworkDownEvent :
\r
384 /* Attempt to establish a connection. */
\r
385 xNetworkUp = pdFALSE;
\r
386 prvProcessNetworkDownEvent();
\r
389 case eNetworkRxEvent:
\r
390 /* The network hardware driver has received a new packet. A
\r
391 pointer to the received buffer is located in the pvData member
\r
392 of the received event structure. */
\r
393 prvHandleEthernetPacket( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ) );
\r
396 case eARPTimerEvent :
\r
397 /* The ARP timer has expired, process the ARP cache. */
\r
401 case eSocketBindEvent:
\r
402 /* FreeRTOS_bind (a user API) wants the IP-task to bind a socket
\r
403 to a port. The port number is communicated in the socket field
\r
404 usLocalPort. vSocketBind() will actually bind the socket and the
\r
405 API will unblock as soon as the eSOCKET_BOUND event is
\r
407 pxSocket = ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData );
\r
408 xAddress.sin_addr = 0u; /* For the moment. */
\r
409 xAddress.sin_port = FreeRTOS_ntohs( pxSocket->usLocalPort );
\r
410 pxSocket->usLocalPort = 0u;
\r
411 vSocketBind( pxSocket, &xAddress, sizeof( xAddress ), pdFALSE );
\r
413 /* Before 'eSocketBindEvent' was sent it was tested that
\r
414 ( xEventGroup != NULL ) so it can be used now to wake up the
\r
416 pxSocket->xEventBits |= eSOCKET_BOUND;
\r
417 vSocketWakeUpUser( pxSocket );
\r
420 case eSocketCloseEvent :
\r
421 /* The user API FreeRTOS_closesocket() has sent a message to the
\r
422 IP-task to actually close a socket. This is handled in
\r
423 vSocketClose(). As the socket gets closed, there is no way to
\r
424 report back to the API, so the API won't wait for the result */
\r
425 vSocketClose( ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData ) );
\r
428 case eStackTxEvent :
\r
429 /* The network stack has generated a packet to send. A
\r
430 pointer to the generated buffer is located in the pvData
\r
431 member of the received event structure. */
\r
432 vProcessGeneratedUDPPacket( ( NetworkBufferDescriptor_t * ) ( xReceivedEvent.pvData ) );
\r
436 /* The DHCP state machine needs processing. */
\r
437 #if( ipconfigUSE_DHCP == 1 )
\r
439 vDHCPProcess( pdFALSE );
\r
441 #endif /* ipconfigUSE_DHCP */
\r
444 case eSocketSelectEvent :
\r
445 /* FreeRTOS_select() has got unblocked by a socket event,
\r
446 vSocketSelect() will check which sockets actually have an event
\r
447 and update the socket field xSocketBits. */
\r
448 #if( ipconfigSUPPORT_SELECT_FUNCTION == 1 )
\r
450 vSocketSelect( ( SocketSelect_t * ) ( xReceivedEvent.pvData ) );
\r
452 #endif /* ipconfigSUPPORT_SELECT_FUNCTION == 1 */
\r
455 case eSocketSignalEvent :
\r
456 #if( ipconfigSUPPORT_SIGNALS != 0 )
\r
458 /* Some task wants to signal the user of this socket in
\r
459 order to interrupt a call to recv() or a call to select(). */
\r
460 FreeRTOS_SignalSocket( ( Socket_t ) xReceivedEvent.pvData );
\r
462 #endif /* ipconfigSUPPORT_SIGNALS */
\r
465 case eTCPTimerEvent :
\r
466 #if( ipconfigUSE_TCP == 1 )
\r
468 /* Simply mark the TCP timer as expired so it gets processed
\r
469 the next time prvCheckNetworkTimers() is called. */
\r
470 xTCPTimer.bExpired = pdTRUE_UNSIGNED;
\r
472 #endif /* ipconfigUSE_TCP */
\r
475 case eTCPAcceptEvent:
\r
476 /* The API FreeRTOS_accept() was called, the IP-task will now
\r
477 check if the listening socket (communicated in pvData) actually
\r
478 received a new connection. */
\r
479 #if( ipconfigUSE_TCP == 1 )
\r
481 pxSocket = ( FreeRTOS_Socket_t * ) ( xReceivedEvent.pvData );
\r
483 if( xTCPCheckNewClient( pxSocket ) != pdFALSE )
\r
485 pxSocket->xEventBits |= eSOCKET_ACCEPT;
\r
486 vSocketWakeUpUser( pxSocket );
\r
489 #endif /* ipconfigUSE_TCP */
\r
493 /* FreeRTOS_netstat() was called to have the IP-task print an
\r
494 overview of all sockets and their connections */
\r
495 #if( ( ipconfigUSE_TCP == 1 ) && ( ipconfigHAS_PRINTF == 1 ) )
\r
499 #endif /* ipconfigUSE_TCP */
\r
503 /* Should not get here. */
\r
507 if( xNetworkDownEventPending != pdFALSE )
\r
509 /* A network down event could not be posted to the network event
\r
510 queue because the queue was full. Try posting again. */
\r
511 FreeRTOS_NetworkDown();
\r
515 /*-----------------------------------------------------------*/
\r
517 BaseType_t xIsCallingFromIPTask( void )
\r
519 BaseType_t xReturn;
\r
521 if( xTaskGetCurrentTaskHandle() == xIPTaskHandle )
\r
532 /*-----------------------------------------------------------*/
\r
534 static void prvHandleEthernetPacket( NetworkBufferDescriptor_t *pxBuffer )
\r
536 #if( ipconfigUSE_LINKED_RX_MESSAGES == 0 )
\r
538 /* When ipconfigUSE_LINKED_RX_MESSAGES is not set to 0 then only one
\r
539 buffer will be sent at a time. This is the default way for +TCP to pass
\r
540 messages from the MAC to the TCP/IP stack. */
\r
541 prvProcessEthernetPacket( pxBuffer );
\r
543 #else /* ipconfigUSE_LINKED_RX_MESSAGES */
\r
545 NetworkBufferDescriptor_t *pxNextBuffer;
\r
547 /* An optimisation that is useful when there is high network traffic.
\r
548 Instead of passing received packets into the IP task one at a time the
\r
549 network interface can chain received packets together and pass them into
\r
550 the IP task in one go. The packets are chained using the pxNextBuffer
\r
551 member. The loop below walks through the chain processing each packet
\r
552 in the chain in turn. */
\r
555 /* Store a pointer to the buffer after pxBuffer for use later on. */
\r
556 pxNextBuffer = pxBuffer->pxNextBuffer;
\r
558 /* Make it NULL to avoid using it later on. */
\r
559 pxBuffer->pxNextBuffer = NULL;
\r
561 prvProcessEthernetPacket( pxBuffer );
\r
562 pxBuffer = pxNextBuffer;
\r
564 /* While there is another packet in the chain. */
\r
565 } while( pxBuffer != NULL );
\r
567 #endif /* ipconfigUSE_LINKED_RX_MESSAGES */
\r
569 /*-----------------------------------------------------------*/
\r
571 static TickType_t prvCalculateSleepTime( void )
\r
573 TickType_t xMaximumSleepTime;
\r
575 /* Start with the maximum sleep time, then check this against the remaining
\r
576 time in any other timers that are active. */
\r
577 xMaximumSleepTime = ipconfigMAX_IP_TASK_SLEEP_TIME;
\r
579 if( xARPTimer.bActive != pdFALSE_UNSIGNED )
\r
581 if( xARPTimer.ulRemainingTime < xMaximumSleepTime )
\r
583 xMaximumSleepTime = xARPTimer.ulReloadTime;
\r
587 #if( ipconfigUSE_DHCP == 1 )
\r
589 if( xDHCPTimer.bActive != pdFALSE_UNSIGNED )
\r
591 if( xDHCPTimer.ulRemainingTime < xMaximumSleepTime )
\r
593 xMaximumSleepTime = xDHCPTimer.ulRemainingTime;
\r
597 #endif /* ipconfigUSE_DHCP */
\r
599 #if( ipconfigUSE_TCP == 1 )
\r
601 if( xTCPTimer.ulRemainingTime < xMaximumSleepTime )
\r
603 xMaximumSleepTime = xTCPTimer.ulRemainingTime;
\r
608 #if( ipconfigDNS_USE_CALLBACKS != 0 )
\r
610 if( xDNSTimer.bActive != pdFALSE )
\r
612 if( xDNSTimer.ulRemainingTime < xMaximumSleepTime )
\r
614 xMaximumSleepTime = xDNSTimer.ulRemainingTime;
\r
620 return xMaximumSleepTime;
\r
622 /*-----------------------------------------------------------*/
\r
624 static void prvCheckNetworkTimers( void )
\r
626 /* Is it time for ARP processing? */
\r
627 if( prvIPTimerCheck( &xARPTimer ) != pdFALSE )
\r
629 xSendEventToIPTask( eARPTimerEvent );
\r
632 #if( ipconfigUSE_DHCP == 1 )
\r
634 /* Is it time for DHCP processing? */
\r
635 if( prvIPTimerCheck( &xDHCPTimer ) != pdFALSE )
\r
637 xSendEventToIPTask( eDHCPEvent );
\r
640 #endif /* ipconfigUSE_DHCP */
\r
642 #if( ipconfigDNS_USE_CALLBACKS != 0 )
\r
644 extern void vDNSCheckCallBack( void *pvSearchID );
\r
646 /* Is it time for DNS processing? */
\r
647 if( prvIPTimerCheck( &xDNSTimer ) != pdFALSE )
\r
649 vDNSCheckCallBack( NULL );
\r
652 #endif /* ipconfigDNS_USE_CALLBACKS */
\r
654 #if( ipconfigUSE_TCP == 1 )
\r
656 BaseType_t xWillSleep;
\r
657 TickType_t xNextTime;
\r
658 BaseType_t xCheckTCPSockets;
\r
660 if( uxQueueMessagesWaiting( xNetworkEventQueue ) == 0u )
\r
662 xWillSleep = pdTRUE;
\r
666 xWillSleep = pdFALSE;
\r
669 /* Sockets need to be checked if the TCP timer has expired. */
\r
670 xCheckTCPSockets = prvIPTimerCheck( &xTCPTimer );
\r
672 /* Sockets will also be checked if there are TCP messages but the
\r
673 message queue is empty (indicated by xWillSleep being true). */
\r
674 if( ( xProcessedTCPMessage != pdFALSE ) && ( xWillSleep != pdFALSE ) )
\r
676 xCheckTCPSockets = pdTRUE;
\r
679 if( xCheckTCPSockets != pdFALSE )
\r
681 /* Attend to the sockets, returning the period after which the
\r
682 check must be repeated. */
\r
683 xNextTime = xTCPTimerCheck( xWillSleep );
\r
684 prvIPTimerStart( &xTCPTimer, xNextTime );
\r
685 xProcessedTCPMessage = 0;
\r
688 #endif /* ipconfigUSE_TCP == 1 */
\r
690 /*-----------------------------------------------------------*/
\r
692 static void prvIPTimerStart( IPTimer_t *pxTimer, TickType_t xTime )
\r
694 vTaskSetTimeOutState( &pxTimer->xTimeOut );
\r
695 pxTimer->ulRemainingTime = xTime;
\r
697 if( xTime == ( TickType_t ) 0 )
\r
699 pxTimer->bExpired = pdTRUE_UNSIGNED;
\r
703 pxTimer->bExpired = pdFALSE_UNSIGNED;
\r
706 pxTimer->bActive = pdTRUE_UNSIGNED;
\r
708 /*-----------------------------------------------------------*/
\r
710 static void prvIPTimerReload( IPTimer_t *pxTimer, TickType_t xTime )
\r
712 pxTimer->ulReloadTime = xTime;
\r
713 prvIPTimerStart( pxTimer, xTime );
\r
715 /*-----------------------------------------------------------*/
\r
717 static BaseType_t prvIPTimerCheck( IPTimer_t *pxTimer )
\r
719 BaseType_t xReturn;
\r
721 if( pxTimer->bActive == pdFALSE_UNSIGNED )
\r
723 /* The timer is not enabled. */
\r
728 /* The timer might have set the bExpired flag already, if not, check the
\r
729 value of xTimeOut against ulRemainingTime. */
\r
730 if( ( pxTimer->bExpired != pdFALSE_UNSIGNED ) ||
\r
731 ( xTaskCheckForTimeOut( &( pxTimer->xTimeOut ), &( pxTimer->ulRemainingTime ) ) != pdFALSE ) )
\r
733 prvIPTimerStart( pxTimer, pxTimer->ulReloadTime );
\r
744 /*-----------------------------------------------------------*/
\r
746 void FreeRTOS_NetworkDown( void )
\r
748 static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };
\r
749 const TickType_t xDontBlock = ( TickType_t ) 0;
\r
751 /* Simply send the network task the appropriate event. */
\r
752 if( xSendEventStructToIPTask( &xNetworkDownEvent, xDontBlock ) != pdPASS )
\r
754 /* Could not send the message, so it is still pending. */
\r
755 xNetworkDownEventPending = pdTRUE;
\r
759 /* Message was sent so it is not pending. */
\r
760 xNetworkDownEventPending = pdFALSE;
\r
763 iptraceNETWORK_DOWN();
\r
765 /*-----------------------------------------------------------*/
\r
767 BaseType_t FreeRTOS_NetworkDownFromISR( void )
\r
769 static const IPStackEvent_t xNetworkDownEvent = { eNetworkDownEvent, NULL };
\r
770 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
\r
772 /* Simply send the network task the appropriate event. */
\r
773 if( xQueueSendToBackFromISR( xNetworkEventQueue, &xNetworkDownEvent, &xHigherPriorityTaskWoken ) != pdPASS )
\r
775 xNetworkDownEventPending = pdTRUE;
\r
779 xNetworkDownEventPending = pdFALSE;
\r
782 iptraceNETWORK_DOWN();
\r
784 return xHigherPriorityTaskWoken;
\r
786 /*-----------------------------------------------------------*/
\r
788 void *FreeRTOS_GetUDPPayloadBuffer( size_t xRequestedSizeBytes, TickType_t xBlockTimeTicks )
\r
790 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
793 /* Cap the block time. The reason for this is explained where
\r
794 ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS is defined (assuming an official
\r
795 FreeRTOSIPConfig.h header file is being used). */
\r
796 if( xBlockTimeTicks > ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS )
\r
798 xBlockTimeTicks = ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS;
\r
801 /* Obtain a network buffer with the required amount of storage. */
\r
802 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( UDPPacket_t ) + xRequestedSizeBytes, xBlockTimeTicks );
\r
804 if( pxNetworkBuffer != NULL )
\r
806 /* Set the actual packet size in case a bigger buffer was returned. */
\r
807 pxNetworkBuffer->xDataLength =
\r
808 sizeof( UDPPacket_t ) + xRequestedSizeBytes;
\r
810 /* Leave space for the UPD header. */
\r
811 pvReturn = ( void * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipUDP_PAYLOAD_OFFSET_IPv4 ] );
\r
818 return ( void * ) pvReturn;
\r
820 /*-----------------------------------------------------------*/
\r
822 NetworkBufferDescriptor_t *pxDuplicateNetworkBufferWithDescriptor( NetworkBufferDescriptor_t * const pxNetworkBuffer,
\r
823 BaseType_t xNewLength )
\r
825 NetworkBufferDescriptor_t * pxNewBuffer;
\r
827 /* This function is only used when 'ipconfigZERO_COPY_TX_DRIVER' is set to 1.
\r
828 The transmit routine wants to have ownership of the network buffer
\r
829 descriptor, because it will pass the buffer straight to DMA. */
\r
830 pxNewBuffer = pxGetNetworkBufferWithDescriptor( ( size_t ) xNewLength, ( TickType_t ) 0 );
\r
832 if( pxNewBuffer != NULL )
\r
834 /* Set the actual packet size in case a bigger buffer than requested
\r
836 pxNewBuffer->xDataLength = xNewLength;
\r
838 /* Copy the original packet information. */
\r
839 pxNewBuffer->ulIPAddress = pxNetworkBuffer->ulIPAddress;
\r
840 pxNewBuffer->usPort = pxNetworkBuffer->usPort;
\r
841 pxNewBuffer->usBoundPort = pxNetworkBuffer->usBoundPort;
\r
842 memcpy( pxNewBuffer->pucEthernetBuffer, pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer->xDataLength );
\r
845 return pxNewBuffer;
\r
847 /*-----------------------------------------------------------*/
\r
849 #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) || ( ipconfigZERO_COPY_RX_DRIVER != 0 )
\r
851 NetworkBufferDescriptor_t *pxPacketBuffer_to_NetworkBuffer( const void *pvBuffer )
\r
853 uint8_t *pucBuffer;
\r
854 NetworkBufferDescriptor_t *pxResult;
\r
856 if( pvBuffer == NULL )
\r
862 /* Obtain the network buffer from the zero copy pointer. */
\r
863 pucBuffer = ( uint8_t * ) pvBuffer;
\r
865 /* The input here is a pointer to a payload buffer. Subtract the
\r
866 size of the header in the network buffer, usually 8 + 2 bytes. */
\r
867 pucBuffer -= ipBUFFER_PADDING;
\r
869 /* Here a pointer was placed to the network descriptor. As a
\r
870 pointer is dereferenced, make sure it is well aligned. */
\r
871 if( ( ( ( uint32_t ) pucBuffer ) & ( sizeof( pucBuffer ) - ( size_t ) 1 ) ) == ( uint32_t ) 0 )
\r
873 pxResult = * ( ( NetworkBufferDescriptor_t ** ) pucBuffer );
\r
884 #endif /* ipconfigZERO_COPY_TX_DRIVER != 0 */
\r
885 /*-----------------------------------------------------------*/
\r
887 NetworkBufferDescriptor_t *pxUDPPayloadBuffer_to_NetworkBuffer( void *pvBuffer )
\r
889 uint8_t *pucBuffer;
\r
890 NetworkBufferDescriptor_t *pxResult;
\r
892 if( pvBuffer == NULL )
\r
898 /* Obtain the network buffer from the zero copy pointer. */
\r
899 pucBuffer = ( uint8_t * ) pvBuffer;
\r
901 /* The input here is a pointer to a payload buffer. Subtract
\r
902 the total size of a UDP/IP header plus the size of the header in
\r
903 the network buffer, usually 8 + 2 bytes. */
\r
904 pucBuffer -= ( sizeof( UDPPacket_t ) + ipBUFFER_PADDING );
\r
906 /* Here a pointer was placed to the network descriptor,
\r
907 As a pointer is dereferenced, make sure it is well aligned */
\r
908 if( ( ( ( uint32_t ) pucBuffer ) & ( sizeof( pucBuffer ) - 1 ) ) == 0 )
\r
910 /* The following statement may trigger a:
\r
911 warning: cast increases required alignment of target type [-Wcast-align].
\r
912 It has been confirmed though that the alignment is suitable. */
\r
913 pxResult = * ( ( NetworkBufferDescriptor_t ** ) pucBuffer );
\r
923 /*-----------------------------------------------------------*/
\r
925 void FreeRTOS_ReleaseUDPPayloadBuffer( void *pvBuffer )
\r
927 vReleaseNetworkBufferAndDescriptor( pxUDPPayloadBuffer_to_NetworkBuffer( pvBuffer ) );
\r
929 /*-----------------------------------------------------------*/
\r
931 /*_RB_ Should we add an error or assert if the task priorities are set such that the servers won't function as expected? */
\r
932 /*_HT_ There was a bug in FreeRTOS_TCP_IP.c that only occurred when the applications' priority was too high.
\r
933 As that bug has been repaired, there is not an urgent reason to warn.
\r
934 It is better though to use the advised priority scheme. */
\r
935 BaseType_t FreeRTOS_IPInit( 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 ] )
\r
937 BaseType_t xReturn = pdFALSE;
\r
939 /* This function should only be called once. */
\r
940 configASSERT( xIPIsNetworkTaskReady() == pdFALSE );
\r
941 configASSERT( xNetworkEventQueue == NULL );
\r
942 configASSERT( xIPTaskHandle == NULL );
\r
944 /* Check structure packing is correct. */
\r
945 configASSERT( sizeof( EthernetHeader_t ) == ipEXPECTED_EthernetHeader_t_SIZE );
\r
946 configASSERT( sizeof( ARPHeader_t ) == ipEXPECTED_ARPHeader_t_SIZE );
\r
947 configASSERT( sizeof( IPHeader_t ) == ipEXPECTED_IPHeader_t_SIZE );
\r
948 configASSERT( sizeof( ICMPHeader_t ) == ipEXPECTED_ICMPHeader_t_SIZE );
\r
949 configASSERT( sizeof( UDPHeader_t ) == ipEXPECTED_UDPHeader_t_SIZE );
\r
951 /* Attempt to create the queue used to communicate with the IP task. */
\r
952 xNetworkEventQueue = xQueueCreate( ( UBaseType_t ) ipconfigEVENT_QUEUE_LENGTH, ( UBaseType_t ) sizeof( IPStackEvent_t ) );
\r
953 configASSERT( xNetworkEventQueue );
\r
955 if( xNetworkEventQueue != NULL )
\r
957 #if ( configQUEUE_REGISTRY_SIZE > 0 )
\r
959 /* A queue registry is normally used to assist a kernel aware
\r
960 debugger. If one is in use then it will be helpful for the debugger
\r
961 to show information about the network event queue. */
\r
962 vQueueAddToRegistry( xNetworkEventQueue, "NetEvnt" );
\r
964 #endif /* configQUEUE_REGISTRY_SIZE */
\r
966 if( xNetworkBuffersInitialise() == pdPASS )
\r
968 /* Store the local IP and MAC address. */
\r
969 xNetworkAddressing.ulDefaultIPAddress = FreeRTOS_inet_addr_quick( ucIPAddress[ 0 ], ucIPAddress[ 1 ], ucIPAddress[ 2 ], ucIPAddress[ 3 ] );
\r
970 xNetworkAddressing.ulNetMask = FreeRTOS_inet_addr_quick( ucNetMask[ 0 ], ucNetMask[ 1 ], ucNetMask[ 2 ], ucNetMask[ 3 ] );
\r
971 xNetworkAddressing.ulGatewayAddress = FreeRTOS_inet_addr_quick( ucGatewayAddress[ 0 ], ucGatewayAddress[ 1 ], ucGatewayAddress[ 2 ], ucGatewayAddress[ 3 ] );
\r
972 xNetworkAddressing.ulDNSServerAddress = FreeRTOS_inet_addr_quick( ucDNSServerAddress[ 0 ], ucDNSServerAddress[ 1 ], ucDNSServerAddress[ 2 ], ucDNSServerAddress[ 3 ] );
\r
973 xNetworkAddressing.ulBroadcastAddress = ( xNetworkAddressing.ulDefaultIPAddress & xNetworkAddressing.ulNetMask ) | ~xNetworkAddressing.ulNetMask;
\r
975 memcpy( &xDefaultAddressing, &xNetworkAddressing, sizeof( xDefaultAddressing ) );
\r
977 #if ipconfigUSE_DHCP == 1
\r
979 /* The IP address is not set until DHCP completes. */
\r
980 *ipLOCAL_IP_ADDRESS_POINTER = 0x00UL;
\r
984 /* The IP address is set from the value passed in. */
\r
985 *ipLOCAL_IP_ADDRESS_POINTER = xNetworkAddressing.ulDefaultIPAddress;
\r
987 /* Added to prevent ARP flood to gateway. Ensure the
\r
988 gateway is on the same subnet as the IP address. */
\r
989 configASSERT( ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) == ( xNetworkAddressing.ulGatewayAddress & xNetworkAddressing.ulNetMask ) );
\r
991 #endif /* ipconfigUSE_DHCP == 1 */
\r
993 /* The MAC address is stored in the start of the default packet
\r
994 header fragment, which is used when sending UDP packets. */
\r
995 memcpy( ( void * ) ipLOCAL_MAC_ADDRESS, ( void * ) ucMACAddress, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
\r
997 /* Prepare the sockets interface. */
\r
998 xReturn = vNetworkSocketsInit();
\r
1000 if( pdTRUE == xReturn )
\r
1002 /* Create the task that processes Ethernet and stack events. */
\r
1003 xReturn = xTaskCreate( prvIPTask, "IP-task", ( uint16_t )ipconfigIP_TASK_STACK_SIZE_WORDS, NULL, ( UBaseType_t )ipconfigIP_TASK_PRIORITY, &xIPTaskHandle );
\r
1008 FreeRTOS_debug_printf( ( "FreeRTOS_IPInit: xNetworkBuffersInitialise() failed\n") );
\r
1011 vQueueDelete( xNetworkEventQueue );
\r
1012 xNetworkEventQueue = NULL;
\r
1017 FreeRTOS_debug_printf( ( "FreeRTOS_IPInit: Network event queue could not be created\n") );
\r
1022 /*-----------------------------------------------------------*/
\r
1024 void FreeRTOS_GetAddressConfiguration( uint32_t *pulIPAddress, uint32_t *pulNetMask, uint32_t *pulGatewayAddress, uint32_t *pulDNSServerAddress )
\r
1026 /* Return the address configuration to the caller. */
\r
1028 if( pulIPAddress != NULL )
\r
1030 *pulIPAddress = *ipLOCAL_IP_ADDRESS_POINTER;
\r
1033 if( pulNetMask != NULL )
\r
1035 *pulNetMask = xNetworkAddressing.ulNetMask;
\r
1038 if( pulGatewayAddress != NULL )
\r
1040 *pulGatewayAddress = xNetworkAddressing.ulGatewayAddress;
\r
1043 if( pulDNSServerAddress != NULL )
\r
1045 *pulDNSServerAddress = xNetworkAddressing.ulDNSServerAddress;
\r
1048 /*-----------------------------------------------------------*/
\r
1050 void FreeRTOS_SetAddressConfiguration( const uint32_t *pulIPAddress, const uint32_t *pulNetMask, const uint32_t *pulGatewayAddress, const uint32_t *pulDNSServerAddress )
\r
1052 /* Update the address configuration. */
\r
1054 if( pulIPAddress != NULL )
\r
1056 *ipLOCAL_IP_ADDRESS_POINTER = *pulIPAddress;
\r
1059 if( pulNetMask != NULL )
\r
1061 xNetworkAddressing.ulNetMask = *pulNetMask;
\r
1064 if( pulGatewayAddress != NULL )
\r
1066 xNetworkAddressing.ulGatewayAddress = *pulGatewayAddress;
\r
1069 if( pulDNSServerAddress != NULL )
\r
1071 xNetworkAddressing.ulDNSServerAddress = *pulDNSServerAddress;
\r
1074 /*-----------------------------------------------------------*/
\r
1076 #if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
\r
1078 BaseType_t FreeRTOS_SendPingRequest( uint32_t ulIPAddress, size_t xNumberOfBytesToSend, TickType_t xBlockTimeTicks )
\r
1080 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
1081 ICMPHeader_t *pxICMPHeader;
\r
1082 BaseType_t xReturn = pdFAIL;
\r
1083 static uint16_t usSequenceNumber = 0;
\r
1085 IPStackEvent_t xStackTxEvent = { eStackTxEvent, NULL };
\r
1087 if( (xNumberOfBytesToSend >= 1 ) && ( xNumberOfBytesToSend < ( ( ipconfigNETWORK_MTU - sizeof( IPHeader_t ) ) - sizeof( ICMPHeader_t ) ) ) && ( uxGetNumberOfFreeNetworkBuffers() >= 3 ) )
\r
1089 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( xNumberOfBytesToSend + sizeof( ICMPPacket_t ), xBlockTimeTicks );
\r
1091 if( pxNetworkBuffer != NULL )
\r
1093 pxICMPHeader = ( ICMPHeader_t * ) &( pxNetworkBuffer->pucEthernetBuffer[ ipIP_PAYLOAD_OFFSET ] );
\r
1094 usSequenceNumber++;
\r
1096 /* Fill in the basic header information. */
\r
1097 pxICMPHeader->ucTypeOfMessage = ipICMP_ECHO_REQUEST;
\r
1098 pxICMPHeader->ucTypeOfService = 0;
\r
1099 pxICMPHeader->usIdentifier = usSequenceNumber;
\r
1100 pxICMPHeader->usSequenceNumber = usSequenceNumber;
\r
1102 /* Find the start of the data. */
\r
1103 pucChar = ( uint8_t * ) pxICMPHeader;
\r
1104 pucChar += sizeof( ICMPHeader_t );
\r
1106 /* Just memset the data to a fixed value. */
\r
1107 memset( ( void * ) pucChar, ( int ) ipECHO_DATA_FILL_BYTE, xNumberOfBytesToSend );
\r
1109 /* The message is complete, IP and checksum's are handled by
\r
1110 vProcessGeneratedUDPPacket */
\r
1111 pxNetworkBuffer->pucEthernetBuffer[ ipSOCKET_OPTIONS_OFFSET ] = FREERTOS_SO_UDPCKSUM_OUT;
\r
1112 pxNetworkBuffer->ulIPAddress = ulIPAddress;
\r
1113 pxNetworkBuffer->usPort = ipPACKET_CONTAINS_ICMP_DATA;
\r
1114 pxNetworkBuffer->xDataLength = xNumberOfBytesToSend + sizeof( ICMPHeader_t );
\r
1116 /* Send to the stack. */
\r
1117 xStackTxEvent.pvData = pxNetworkBuffer;
\r
1119 if( xSendEventStructToIPTask( &xStackTxEvent, xBlockTimeTicks) != pdPASS )
\r
1121 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
1122 iptraceSTACK_TX_EVENT_LOST( ipSTACK_TX_EVENT );
\r
1126 xReturn = usSequenceNumber;
\r
1132 /* The requested number of bytes will not fit in the available space
\r
1133 in the network buffer. */
\r
1139 #endif /* ipconfigSUPPORT_OUTGOING_PINGS == 1 */
\r
1140 /*-----------------------------------------------------------*/
\r
1142 BaseType_t xSendEventToIPTask( eIPEvent_t eEvent )
\r
1144 IPStackEvent_t xEventMessage;
\r
1145 const TickType_t xDontBlock = ( TickType_t ) 0;
\r
1147 xEventMessage.eEventType = eEvent;
\r
1148 xEventMessage.pvData = ( void* )NULL;
\r
1150 return xSendEventStructToIPTask( &xEventMessage, xDontBlock );
\r
1152 /*-----------------------------------------------------------*/
\r
1154 BaseType_t xSendEventStructToIPTask( const IPStackEvent_t *pxEvent, TickType_t xTimeout )
\r
1156 BaseType_t xReturn, xSendMessage;
\r
1158 if( ( xIPIsNetworkTaskReady() == pdFALSE ) && ( pxEvent->eEventType != eNetworkDownEvent ) )
\r
1160 /* Only allow eNetworkDownEvent events if the IP task is not ready
\r
1161 yet. Not going to attempt to send the message so the send failed. */
\r
1166 xSendMessage = pdTRUE;
\r
1168 #if( ipconfigUSE_TCP == 1 )
\r
1170 if( pxEvent->eEventType == eTCPTimerEvent )
\r
1172 /* TCP timer events are sent to wake the timer task when
\r
1173 xTCPTimer has expired, but there is no point sending them if the
\r
1174 IP task is already awake processing other message. */
\r
1175 xTCPTimer.bExpired = pdTRUE_UNSIGNED;
\r
1177 if( uxQueueMessagesWaiting( xNetworkEventQueue ) != 0u )
\r
1179 /* Not actually going to send the message but this is not a
\r
1180 failure as the message didn't need to be sent. */
\r
1181 xSendMessage = pdFALSE;
\r
1185 #endif /* ipconfigUSE_TCP */
\r
1187 if( xSendMessage != pdFALSE )
\r
1189 /* The IP task cannot block itself while waiting for itself to
\r
1191 if( ( xIsCallingFromIPTask() == pdTRUE ) && ( xTimeout > ( TickType_t ) 0 ) )
\r
1193 xTimeout = ( TickType_t ) 0;
\r
1196 xReturn = xQueueSendToBack( xNetworkEventQueue, pxEvent, xTimeout );
\r
1198 if( xReturn == pdFAIL )
\r
1200 /* A message should have been sent to the IP task, but wasn't. */
\r
1201 FreeRTOS_debug_printf( ( "xSendEventStructToIPTask: CAN NOT ADD %d\n", pxEvent->eEventType ) );
\r
1202 iptraceSTACK_TX_EVENT_LOST( pxEvent->eEventType );
\r
1207 /* It was not necessary to send the message to process the event so
\r
1208 even though the message was not sent the call was successful. */
\r
1215 /*-----------------------------------------------------------*/
\r
1217 eFrameProcessingResult_t eConsiderFrameForProcessing( const uint8_t * const pucEthernetBuffer )
\r
1219 eFrameProcessingResult_t eReturn;
\r
1220 const EthernetHeader_t *pxEthernetHeader;
\r
1222 pxEthernetHeader = ( const EthernetHeader_t * ) pucEthernetBuffer;
\r
1224 if( memcmp( ( void * ) ipLOCAL_MAC_ADDRESS, ( void * ) &( pxEthernetHeader->xDestinationAddress ), sizeof( MACAddress_t ) ) == 0 )
\r
1226 /* The packet was directed to this node directly - process it. */
\r
1227 eReturn = eProcessBuffer;
\r
1229 else if( memcmp( ( void * ) xBroadcastMACAddress.ucBytes, ( void * ) pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
\r
1231 /* The packet was a broadcast - process it. */
\r
1232 eReturn = eProcessBuffer;
\r
1235 #if( ipconfigUSE_LLMNR == 1 )
\r
1236 if( memcmp( ( void * ) xLLMNR_MacAdress.ucBytes, ( void * ) pxEthernetHeader->xDestinationAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
\r
1238 /* The packet is a request for LLMNR - process it. */
\r
1239 eReturn = eProcessBuffer;
\r
1242 #endif /* ipconfigUSE_LLMNR */
\r
1244 /* The packet was not a broadcast, or for this node, just release
\r
1245 the buffer without taking any other action. */
\r
1246 eReturn = eReleaseBuffer;
\r
1249 #if( ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES == 1 )
\r
1251 uint16_t usFrameType;
\r
1253 if( eReturn == eProcessBuffer )
\r
1255 usFrameType = pxEthernetHeader->usFrameType;
\r
1256 usFrameType = FreeRTOS_ntohs( usFrameType );
\r
1258 if( usFrameType <= 0x600U )
\r
1260 /* Not an Ethernet II frame. */
\r
1261 eReturn = eReleaseBuffer;
\r
1265 #endif /* ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES == 1 */
\r
1269 /*-----------------------------------------------------------*/
\r
1271 static void prvProcessNetworkDownEvent( void )
\r
1273 /* Stop the ARP timer while there is no network. */
\r
1274 xARPTimer.bActive = pdFALSE_UNSIGNED;
\r
1276 #if ipconfigUSE_NETWORK_EVENT_HOOK == 1
\r
1278 static BaseType_t xCallEventHook = pdFALSE;
\r
1280 /* The first network down event is generated by the IP stack itself to
\r
1281 initialise the network hardware, so do not call the network down event
\r
1282 the first time through. */
\r
1283 if( xCallEventHook == pdTRUE )
\r
1285 vApplicationIPNetworkEventHook( eNetworkDown );
\r
1287 xCallEventHook = pdTRUE;
\r
1291 /* The network has been disconnected (or is being initialised for the first
\r
1292 time). Perform whatever hardware processing is necessary to bring it up
\r
1293 again, or wait for it to be available again. This is hardware dependent. */
\r
1294 if( xNetworkInterfaceInitialise() != pdPASS )
\r
1296 /* Ideally the network interface initialisation function will only
\r
1297 return when the network is available. In case this is not the case,
\r
1298 wait a while before retrying the initialisation. */
\r
1299 vTaskDelay( ipINITIALISATION_RETRY_DELAY );
\r
1300 FreeRTOS_NetworkDown();
\r
1304 /* Set remaining time to 0 so it will become active immediately. */
\r
1305 #if ipconfigUSE_DHCP == 1
\r
1307 /* The network is not up until DHCP has completed. */
\r
1308 vDHCPProcess( pdTRUE );
\r
1309 xSendEventToIPTask( eDHCPEvent );
\r
1313 /* Perform any necessary 'network up' processing. */
\r
1314 vIPNetworkUpCalls();
\r
1319 /*-----------------------------------------------------------*/
\r
1321 void vIPNetworkUpCalls( void )
\r
1323 xNetworkUp = pdTRUE;
\r
1325 #if( ipconfigUSE_NETWORK_EVENT_HOOK == 1 )
\r
1327 vApplicationIPNetworkEventHook( eNetworkUp );
\r
1329 #endif /* ipconfigUSE_NETWORK_EVENT_HOOK */
\r
1331 #if( ipconfigDNS_USE_CALLBACKS != 0 )
\r
1333 /* The following function is declared in FreeRTOS_DNS.c and 'private' to
\r
1335 extern void vDNSInitialise( void );
\r
1338 #endif /* ipconfigDNS_USE_CALLBACKS != 0 */
\r
1340 /* Set remaining time to 0 so it will become active immediately. */
\r
1341 prvIPTimerReload( &xARPTimer, pdMS_TO_TICKS( ipARP_TIMER_PERIOD_MS ) );
\r
1343 /*-----------------------------------------------------------*/
\r
1345 static void prvProcessEthernetPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
\r
1347 EthernetHeader_t *pxEthernetHeader;
\r
1348 eFrameProcessingResult_t eReturned = eReleaseBuffer;
\r
1350 configASSERT( pxNetworkBuffer );
\r
1352 /* Interpret the Ethernet frame. */
\r
1353 if( pxNetworkBuffer->xDataLength >= sizeof( EthernetHeader_t ) )
\r
1355 eReturned = ipCONSIDER_FRAME_FOR_PROCESSING( pxNetworkBuffer->pucEthernetBuffer );
\r
1356 pxEthernetHeader = ( EthernetHeader_t * )( pxNetworkBuffer->pucEthernetBuffer );
\r
1358 if( eReturned == eProcessBuffer )
\r
1360 /* Interpret the received Ethernet packet. */
\r
1361 switch( pxEthernetHeader->usFrameType )
\r
1363 case ipARP_FRAME_TYPE:
\r
1364 /* The Ethernet frame contains an ARP packet. */
\r
1365 if( pxNetworkBuffer->xDataLength >= sizeof( ARPPacket_t ) )
\r
1367 eReturned = eARPProcessPacket( ( ARPPacket_t * )pxNetworkBuffer->pucEthernetBuffer );
\r
1371 eReturned = eReleaseBuffer;
\r
1375 case ipIPv4_FRAME_TYPE:
\r
1376 /* The Ethernet frame contains an IP packet. */
\r
1377 if( pxNetworkBuffer->xDataLength >= sizeof( IPPacket_t ) )
\r
1379 eReturned = prvProcessIPPacket( ( IPPacket_t * )pxNetworkBuffer->pucEthernetBuffer, pxNetworkBuffer );
\r
1383 eReturned = eReleaseBuffer;
\r
1388 /* No other packet types are handled. Nothing to do. */
\r
1389 eReturned = eReleaseBuffer;
\r
1395 /* Perform any actions that resulted from processing the Ethernet frame. */
\r
1396 switch( eReturned )
\r
1398 case eReturnEthernetFrame :
\r
1399 /* The Ethernet frame will have been updated (maybe it was
\r
1400 an ARP request or a PING request?) and should be sent back to
\r
1402 vReturnEthernetFrame( pxNetworkBuffer, pdTRUE );
\r
1403 /* parameter pdTRUE: the buffer must be released once
\r
1404 the frame has been transmitted */
\r
1407 case eFrameConsumed :
\r
1408 /* The frame is in use somewhere, don't release the buffer
\r
1413 /* The frame is not being used anywhere, and the
\r
1414 NetworkBufferDescriptor_t structure containing the frame should
\r
1415 just be released back to the list of free buffers. */
\r
1416 vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer );
\r
1420 /*-----------------------------------------------------------*/
\r
1422 static eFrameProcessingResult_t prvAllowIPPacket( const IPPacket_t * const pxIPPacket,
\r
1423 NetworkBufferDescriptor_t * const pxNetworkBuffer, UBaseType_t uxHeaderLength )
\r
1425 eFrameProcessingResult_t eReturn = eProcessBuffer;
\r
1427 #if( ( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 ) || ( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 ) )
\r
1428 const IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
\r
1430 /* or else, the parameter won't be used and the function will be optimised
\r
1432 ( void ) pxIPPacket;
\r
1435 #if( ipconfigETHERNET_DRIVER_FILTERS_PACKETS == 0 )
\r
1437 /* In systems with a very small amount of RAM, it might be advantageous
\r
1438 to have incoming messages checked earlier, by the network card driver.
\r
1439 This method may decrease the usage of sparse network buffers. */
\r
1440 uint32_t ulDestinationIPAddress = pxIPHeader->ulDestinationIPAddress;
\r
1442 /* Ensure that the incoming packet is not fragmented (only outgoing
\r
1443 packets can be fragmented) as these are the only handled IP frames
\r
1445 if( ( pxIPHeader->usFragmentOffset & ipFRAGMENT_OFFSET_BIT_MASK ) != 0U )
\r
1447 /* Can not handle, fragmented packet. */
\r
1448 eReturn = eReleaseBuffer;
\r
1450 /* 0x45 means: IPv4 with an IP header of 5 x 4 = 20 bytes
\r
1451 * 0x47 means: IPv4 with an IP header of 7 x 4 = 28 bytes */
\r
1452 else if( ( pxIPHeader->ucVersionHeaderLength < 0x45u ) || ( pxIPHeader->ucVersionHeaderLength > 0x4Fu ) )
\r
1454 /* Can not handle, unknown or invalid header version. */
\r
1455 eReturn = eReleaseBuffer;
\r
1457 /* Is the packet for this IP address? */
\r
1458 else if( ( ulDestinationIPAddress != *ipLOCAL_IP_ADDRESS_POINTER ) &&
\r
1459 /* Is it the global broadcast address 255.255.255.255 ? */
\r
1460 ( ulDestinationIPAddress != ipBROADCAST_IP_ADDRESS ) &&
\r
1461 /* Is it a specific broadcast address 192.168.1.255 ? */
\r
1462 ( ulDestinationIPAddress != xNetworkAddressing.ulBroadcastAddress ) &&
\r
1463 #if( ipconfigUSE_LLMNR == 1 )
\r
1464 /* Is it the LLMNR multicast address? */
\r
1465 ( ulDestinationIPAddress != ipLLMNR_IP_ADDR ) &&
\r
1467 /* Or (during DHCP negotiation) we have no IP-address yet? */
\r
1468 ( *ipLOCAL_IP_ADDRESS_POINTER != 0UL ) )
\r
1470 /* Packet is not for this node, release it */
\r
1471 eReturn = eReleaseBuffer;
\r
1474 #endif /* ipconfigETHERNET_DRIVER_FILTERS_PACKETS */
\r
1476 #if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 )
\r
1478 /* Some drivers of NIC's with checksum-offloading will enable the above
\r
1479 define, so that the checksum won't be checked again here */
\r
1480 if (eReturn == eProcessBuffer )
\r
1482 /* Is the IP header checksum correct? */
\r
1483 if( ( pxIPHeader->ucProtocol != ( uint8_t ) ipPROTOCOL_ICMP ) &&
\r
1484 ( usGenerateChecksum( 0UL, ( uint8_t * ) &( pxIPHeader->ucVersionHeaderLength ), ( size_t ) uxHeaderLength ) != ipCORRECT_CRC ) )
\r
1486 /* Check sum in IP-header not correct. */
\r
1487 eReturn = eReleaseBuffer;
\r
1489 /* Is the upper-layer checksum (TCP/UDP/ICMP) correct? */
\r
1490 else if( usGenerateProtocolChecksum( ( uint8_t * )( pxNetworkBuffer->pucEthernetBuffer ), pxNetworkBuffer->xDataLength, pdFALSE ) != ipCORRECT_CRC )
\r
1492 /* Protocol checksum not accepted. */
\r
1493 eReturn = eReleaseBuffer;
\r
1499 /* to avoid warning unused parameters */
\r
1500 ( void ) pxNetworkBuffer;
\r
1501 ( void ) uxHeaderLength;
\r
1503 #endif /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM == 0 */
\r
1507 /*-----------------------------------------------------------*/
\r
1509 static eFrameProcessingResult_t prvProcessIPPacket( IPPacket_t * const pxIPPacket, NetworkBufferDescriptor_t * const pxNetworkBuffer )
\r
1511 eFrameProcessingResult_t eReturn;
\r
1512 IPHeader_t * pxIPHeader = &( pxIPPacket->xIPHeader );
\r
1513 UBaseType_t uxHeaderLength = ( UBaseType_t ) ( ( pxIPHeader->ucVersionHeaderLength & 0x0Fu ) << 2 );
\r
1514 uint8_t ucProtocol;
\r
1516 /* Bound the calculated header length: take away the Ethernet header size,
\r
1517 then check if the IP header is claiming to be longer than the remaining
\r
1518 total packet size. Also check for minimal header field length. */
\r
1519 if( uxHeaderLength > pxNetworkBuffer->xDataLength - ipSIZE_OF_ETH_HEADER ||
\r
1520 uxHeaderLength < ipSIZE_OF_IPv4_HEADER )
\r
1522 return eReleaseBuffer;
\r
1525 ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
\r
1526 /* Check if the IP headers are acceptable and if it has our destination. */
\r
1527 eReturn = prvAllowIPPacket( pxIPPacket, pxNetworkBuffer, uxHeaderLength );
\r
1529 if( eReturn == eProcessBuffer )
\r
1531 if( uxHeaderLength > ipSIZE_OF_IPv4_HEADER )
\r
1533 /* All structs of headers expect a IP header size of 20 bytes
\r
1534 * IP header options were included, we'll ignore them and cut them out
\r
1535 * Note: IP options are mostly use in Multi-cast protocols */
\r
1536 const size_t optlen = ( ( size_t ) uxHeaderLength ) - ipSIZE_OF_IPv4_HEADER;
\r
1537 /* From: the previous start of UDP/ICMP/TCP data */
\r
1538 uint8_t *pucSource = ( uint8_t* )(pxNetworkBuffer->pucEthernetBuffer + sizeof( EthernetHeader_t ) + uxHeaderLength);
\r
1539 /* To: the usual start of UDP/ICMP/TCP data at offset 20 from IP header */
\r
1540 uint8_t *pucTarget = ( uint8_t* )(pxNetworkBuffer->pucEthernetBuffer + sizeof( EthernetHeader_t ) + ipSIZE_OF_IPv4_HEADER);
\r
1541 /* How many: total length minus the options and the lower headers */
\r
1542 const size_t xMoveLen = pxNetworkBuffer->xDataLength - optlen - ipSIZE_OF_IPv4_HEADER - ipSIZE_OF_ETH_HEADER;
\r
1544 memmove( pucTarget, pucSource, xMoveLen );
\r
1545 pxNetworkBuffer->xDataLength -= optlen;
\r
1547 /* Fix-up new version/header length field in IP packet. */
\r
1548 pxIPHeader->ucVersionHeaderLength =
\r
1549 ( pxIPHeader->ucVersionHeaderLength & 0xF0 ) | /* High nibble is the version. */
\r
1550 ( ( ipSIZE_OF_IPv4_HEADER >> 2 ) & 0x0F ); /* Low nibble is the header size, in bytes, divided by four. */
\r
1553 /* Add the IP and MAC addresses to the ARP table if they are not
\r
1554 already there - otherwise refresh the age of the existing
\r
1556 if( ucProtocol != ( uint8_t ) ipPROTOCOL_UDP )
\r
1558 /* Refresh the ARP cache with the IP/MAC-address of the received packet
\r
1559 * For UDP packets, this will be done later in xProcessReceivedUDPPacket()
\r
1560 * as soon as know that the message will be handled by someone
\r
1561 * This will prevent that the ARP cache will get overwritten
\r
1562 * with the IP-address of useless broadcast packets
\r
1564 vARPRefreshCacheEntry( &( pxIPPacket->xEthernetHeader.xSourceAddress ), pxIPHeader->ulSourceIPAddress );
\r
1566 switch( ucProtocol )
\r
1568 case ipPROTOCOL_ICMP :
\r
1569 /* The IP packet contained an ICMP frame. Don't bother
\r
1570 checking the ICMP checksum, as if it is wrong then the
\r
1571 wrong data will also be returned, and the source of the
\r
1572 ping will know something went wrong because it will not
\r
1573 be able to validate what it receives. */
\r
1574 #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
\r
1576 if( pxNetworkBuffer->xDataLength >= sizeof( ICMPPacket_t ) )
\r
1578 ICMPPacket_t *pxICMPPacket = ( ICMPPacket_t * )( pxNetworkBuffer->pucEthernetBuffer );
\r
1579 if( pxIPHeader->ulDestinationIPAddress == *ipLOCAL_IP_ADDRESS_POINTER )
\r
1581 eReturn = prvProcessICMPPacket( pxICMPPacket );
\r
1586 eReturn = eReleaseBuffer;
\r
1589 #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
\r
1592 case ipPROTOCOL_UDP :
\r
1594 /* The IP packet contained a UDP frame. */
\r
1595 UDPPacket_t *pxUDPPacket = ( UDPPacket_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
\r
1597 /* Only proceed if the payload length indicated in the header
\r
1598 appears to be valid. */
\r
1599 if ( pxNetworkBuffer->xDataLength >= sizeof( UDPPacket_t ) )
\r
1601 /* Ensure that downstream UDP packet handling has the lesser
\r
1602 * of: the actual network buffer Ethernet frame length, or
\r
1603 * the sender's UDP packet header payload length, minus the
\r
1604 * size of the UDP header.
\r
1606 * The size of the UDP packet structure in this implementation
\r
1607 * includes the size of the Ethernet header, the size of
\r
1608 * the IP header, and the size of the UDP header.
\r
1611 pxNetworkBuffer->xDataLength -= sizeof( UDPPacket_t );
\r
1612 if( ( FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) - sizeof( UDPHeader_t ) ) <
\r
1613 pxNetworkBuffer->xDataLength )
\r
1615 pxNetworkBuffer->xDataLength = FreeRTOS_ntohs( pxUDPPacket->xUDPHeader.usLength ) -
\r
1616 sizeof( UDPHeader_t );
\r
1619 /* Fields in pxNetworkBuffer (usPort, ulIPAddress) are network order. */
\r
1620 pxNetworkBuffer->usPort = pxUDPPacket->xUDPHeader.usSourcePort;
\r
1621 pxNetworkBuffer->ulIPAddress = pxUDPPacket->xIPHeader.ulSourceIPAddress;
\r
1623 /* ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM:
\r
1624 * In some cases, the upper-layer checksum has been calculated
\r
1625 * by the NIC driver.
\r
1627 * Pass the packet payload to the UDP sockets implementation. */
\r
1628 if( xProcessReceivedUDPPacket( pxNetworkBuffer,
\r
1629 pxUDPPacket->xUDPHeader.usDestinationPort ) == pdPASS )
\r
1631 eReturn = eFrameConsumed;
\r
1636 eReturn = eReleaseBuffer;
\r
1641 #if ipconfigUSE_TCP == 1
\r
1642 case ipPROTOCOL_TCP :
\r
1645 if( xProcessReceivedTCPPacket( pxNetworkBuffer ) == pdPASS )
\r
1647 eReturn = eFrameConsumed;
\r
1650 /* Setting this variable will cause xTCPTimerCheck()
\r
1651 to be called just before the IP-task blocks. */
\r
1652 xProcessedTCPMessage++;
\r
1657 /* Not a supported frame type. */
\r
1664 /*-----------------------------------------------------------*/
\r
1666 #if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
\r
1668 static void prvProcessICMPEchoReply( ICMPPacket_t * const pxICMPPacket )
\r
1670 ePingReplyStatus_t eStatus = eSuccess;
\r
1671 uint16_t usDataLength, usCount;
\r
1674 /* Find the total length of the IP packet. */
\r
1675 usDataLength = pxICMPPacket->xIPHeader.usLength;
\r
1676 usDataLength = FreeRTOS_ntohs( usDataLength );
\r
1678 /* Remove the length of the IP headers to obtain the length of the ICMP
\r
1679 message itself. */
\r
1680 usDataLength = ( uint16_t ) ( ( ( uint32_t ) usDataLength ) - ipSIZE_OF_IPv4_HEADER );
\r
1682 /* Remove the length of the ICMP header, to obtain the length of
\r
1683 data contained in the ping. */
\r
1684 usDataLength = ( uint16_t ) ( ( ( uint32_t ) usDataLength ) - ipSIZE_OF_ICMP_HEADER );
\r
1686 /* Checksum has already been checked before in prvProcessIPPacket */
\r
1688 /* Find the first byte of the data within the ICMP packet. */
\r
1689 pucByte = ( uint8_t * ) pxICMPPacket;
\r
1690 pucByte += sizeof( ICMPPacket_t );
\r
1692 /* Check each byte. */
\r
1693 for( usCount = 0; usCount < usDataLength; usCount++ )
\r
1695 if( *pucByte != ipECHO_DATA_FILL_BYTE )
\r
1697 eStatus = eInvalidData;
\r
1704 /* Call back into the application to pass it the result. */
\r
1705 vApplicationPingReplyHook( eStatus, pxICMPPacket->xICMPHeader.usIdentifier );
\r
1709 /*-----------------------------------------------------------*/
\r
1711 #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 )
\r
1713 static eFrameProcessingResult_t prvProcessICMPEchoRequest( ICMPPacket_t * const pxICMPPacket )
\r
1715 ICMPHeader_t *pxICMPHeader;
\r
1716 IPHeader_t *pxIPHeader;
\r
1717 uint16_t usRequest;
\r
1719 pxICMPHeader = &( pxICMPPacket->xICMPHeader );
\r
1720 pxIPHeader = &( pxICMPPacket->xIPHeader );
\r
1722 /* HT:endian: changed back */
\r
1723 iptraceSENDING_PING_REPLY( pxIPHeader->ulSourceIPAddress );
\r
1725 /* The checksum can be checked here - but a ping reply should be
\r
1726 returned even if the checksum is incorrect so the other end can
\r
1727 tell that the ping was received - even if the ping reply contains
\r
1729 pxICMPHeader->ucTypeOfMessage = ( uint8_t ) ipICMP_ECHO_REPLY;
\r
1730 pxIPHeader->ulDestinationIPAddress = pxIPHeader->ulSourceIPAddress;
\r
1731 pxIPHeader->ulSourceIPAddress = *ipLOCAL_IP_ADDRESS_POINTER;
\r
1733 /* Update the checksum because the ucTypeOfMessage member in the header
\r
1734 has been changed to ipICMP_ECHO_REPLY. This is faster than calling
\r
1735 usGenerateChecksum(). */
\r
1737 /* due to compiler warning "integer operation result is out of range" */
\r
1739 usRequest = ( uint16_t ) ( ( uint16_t )ipICMP_ECHO_REQUEST << 8 );
\r
1741 if( pxICMPHeader->usChecksum >= FreeRTOS_htons( 0xFFFFu - usRequest ) )
\r
1743 pxICMPHeader->usChecksum = ( uint16_t )
\r
1744 ( ( ( uint32_t ) pxICMPHeader->usChecksum ) +
\r
1745 FreeRTOS_htons( usRequest + 1UL ) );
\r
1749 pxICMPHeader->usChecksum = ( uint16_t )
\r
1750 ( ( ( uint32_t ) pxICMPHeader->usChecksum ) +
\r
1751 FreeRTOS_htons( usRequest ) );
\r
1753 return eReturnEthernetFrame;
\r
1756 #endif /* ipconfigREPLY_TO_INCOMING_PINGS == 1 */
\r
1757 /*-----------------------------------------------------------*/
\r
1759 #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
\r
1761 static eFrameProcessingResult_t prvProcessICMPPacket( ICMPPacket_t * const pxICMPPacket )
\r
1763 eFrameProcessingResult_t eReturn = eReleaseBuffer;
\r
1765 iptraceICMP_PACKET_RECEIVED();
\r
1766 switch( pxICMPPacket->xICMPHeader.ucTypeOfMessage )
\r
1768 case ipICMP_ECHO_REQUEST :
\r
1769 #if ( ipconfigREPLY_TO_INCOMING_PINGS == 1 )
\r
1771 eReturn = prvProcessICMPEchoRequest( pxICMPPacket );
\r
1773 #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) */
\r
1776 case ipICMP_ECHO_REPLY :
\r
1777 #if ( ipconfigSUPPORT_OUTGOING_PINGS == 1 )
\r
1779 prvProcessICMPEchoReply( pxICMPPacket );
\r
1781 #endif /* ipconfigSUPPORT_OUTGOING_PINGS */
\r
1791 #endif /* ( ipconfigREPLY_TO_INCOMING_PINGS == 1 ) || ( ipconfigSUPPORT_OUTGOING_PINGS == 1 ) */
\r
1792 /*-----------------------------------------------------------*/
\r
1794 uint16_t usGenerateProtocolChecksum( const uint8_t * const pucEthernetBuffer, size_t uxBufferLength, BaseType_t xOutgoingPacket )
\r
1796 uint32_t ulLength;
\r
1797 uint16_t usChecksum, *pusChecksum;
\r
1798 const IPPacket_t * pxIPPacket;
\r
1799 UBaseType_t uxIPHeaderLength;
\r
1800 ProtocolPacket_t *pxProtPack;
\r
1801 uint8_t ucProtocol;
\r
1802 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1803 const char *pcType;
\r
1806 /* Check for minimum packet size. */
\r
1807 if( uxBufferLength < sizeof( IPPacket_t ) )
\r
1809 return ipINVALID_LENGTH;
\r
1812 /* Parse the packet length. */
\r
1813 pxIPPacket = ( const IPPacket_t * ) pucEthernetBuffer;
\r
1815 /* Per https://tools.ietf.org/html/rfc791, the four-bit Internet Header
\r
1816 Length field contains the length of the internet header in 32-bit words. */
\r
1817 uxIPHeaderLength = ( UBaseType_t )
\r
1818 ( sizeof( uint32_t ) * ( pxIPPacket->xIPHeader.ucVersionHeaderLength & 0x0Fu ) );
\r
1820 /* Check for minimum packet size. */
\r
1821 if( uxBufferLength < sizeof( IPPacket_t ) + uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER )
\r
1823 return ipINVALID_LENGTH;
\r
1825 if( uxBufferLength < FreeRTOS_ntohs( pxIPPacket->xIPHeader.usLength ) )
\r
1827 return ipINVALID_LENGTH;
\r
1830 /* Identify the next protocol. */
\r
1831 ucProtocol = pxIPPacket->xIPHeader.ucProtocol;
\r
1833 /* N.B., if this IP packet header includes Options, then the following
\r
1834 assignment results in a pointer into the protocol packet with the Ethernet
\r
1835 and IP headers incorrectly aligned. However, either way, the "third"
\r
1836 protocol (Layer 3 or 4) header will be aligned, which is the convenience
\r
1837 of this calculation. */
\r
1838 pxProtPack = ( ProtocolPacket_t * ) ( pucEthernetBuffer + ( uxIPHeaderLength - ipSIZE_OF_IPv4_HEADER ) );
\r
1840 /* Switch on the Layer 3/4 protocol. */
\r
1841 if( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP )
\r
1843 if( uxBufferLength < uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_UDP_HEADER )
\r
1845 return ipINVALID_LENGTH;
\r
1848 pusChecksum = ( uint16_t * ) ( &( pxProtPack->xUDPPacket.xUDPHeader.usChecksum ) );
\r
1849 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1853 #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
\r
1855 else if( ucProtocol == ( uint8_t ) ipPROTOCOL_TCP )
\r
1857 if( uxBufferLength < uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_TCP_HEADER )
\r
1859 return ipINVALID_LENGTH;
\r
1862 pusChecksum = ( uint16_t * ) ( &( pxProtPack->xTCPPacket.xTCPHeader.usChecksum ) );
\r
1863 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1867 #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
\r
1869 else if( ( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP ) ||
\r
1870 ( ucProtocol == ( uint8_t ) ipPROTOCOL_IGMP ) )
\r
1872 if( uxBufferLength < uxIPHeaderLength + ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ICMP_HEADER )
\r
1874 return ipINVALID_LENGTH;
\r
1877 pusChecksum = ( uint16_t * ) ( &( pxProtPack->xICMPPacket.xICMPHeader.usChecksum ) );
\r
1878 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1880 if( ucProtocol == ( uint8_t ) ipPROTOCOL_ICMP )
\r
1889 #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
\r
1893 /* Unhandled protocol, other than ICMP, IGMP, UDP, or TCP. */
\r
1894 return ipUNHANDLED_PROTOCOL;
\r
1897 /* The protocol and checksum field have been identified. Check the direction
\r
1899 if( xOutgoingPacket != pdFALSE )
\r
1901 /* This is an outgoing packet. Before calculating the checksum, set it
\r
1903 *( pusChecksum ) = 0u;
\r
1905 else if( ( *pusChecksum == 0u ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
\r
1907 /* Sender hasn't set the checksum, no use to calculate it. */
\r
1908 return ipCORRECT_CRC;
\r
1911 ulLength = ( uint32_t )
\r
1912 ( FreeRTOS_ntohs( pxIPPacket->xIPHeader.usLength ) - ( ( uint16_t ) uxIPHeaderLength ) ); /* normally minus 20 */
\r
1914 if( ( ulLength < sizeof( pxProtPack->xUDPPacket.xUDPHeader ) ) ||
\r
1915 ( ulLength > ( uint32_t )( ipconfigNETWORK_MTU - uxIPHeaderLength ) ) )
\r
1917 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1919 FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: len invalid: %lu\n", pcType, ulLength ) );
\r
1921 #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
\r
1923 /* Again, in a 16-bit return value there is no space to indicate an
\r
1924 error. For incoming packets, 0x1234 will cause dropping of the packet.
\r
1925 For outgoing packets, there is a serious problem with the
\r
1927 return ipINVALID_LENGTH;
\r
1929 if( ucProtocol <= ( uint8_t ) ipPROTOCOL_IGMP )
\r
1931 /* ICMP/IGMP do not have a pseudo header for CRC-calculation. */
\r
1932 usChecksum = ( uint16_t )
\r
1933 ( ~usGenerateChecksum( 0UL,
\r
1934 ( uint8_t * ) &( pxProtPack->xTCPPacket.xTCPHeader ), ( size_t ) ulLength ) );
\r
1938 /* For UDP and TCP, sum the pseudo header, i.e. IP protocol + length
\r
1940 usChecksum = ( uint16_t ) ( ulLength + ( ( uint16_t ) ucProtocol ) );
\r
1942 /* And then continue at the IPv4 source and destination addresses. */
\r
1943 usChecksum = ( uint16_t )
\r
1944 ( ~usGenerateChecksum( ( uint32_t ) usChecksum, ( uint8_t * )&( pxIPPacket->xIPHeader.ulSourceIPAddress ),
\r
1945 ( 2u * sizeof( pxIPPacket->xIPHeader.ulSourceIPAddress ) + ulLength ) ) );
\r
1947 /* Sum TCP header and data. */
\r
1950 if( xOutgoingPacket == pdFALSE )
\r
1952 /* This is in incoming packet. If the CRC is correct, it should be zero. */
\r
1953 if( usChecksum == 0u )
\r
1955 usChecksum = ( uint16_t )ipCORRECT_CRC;
\r
1960 if( ( usChecksum == 0u ) && ( ucProtocol == ( uint8_t ) ipPROTOCOL_UDP ) )
\r
1962 /* In case of UDP, a calculated checksum of 0x0000 is transmitted
\r
1963 as 0xffff. A value of zero would mean that the checksum is not used. */
\r
1964 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1966 if( xOutgoingPacket != pdFALSE )
\r
1968 FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04X\n", pcType, usChecksum ) );
\r
1971 #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
\r
1973 usChecksum = ( uint16_t )0xffffu;
\r
1976 usChecksum = FreeRTOS_htons( usChecksum );
\r
1978 if( xOutgoingPacket != pdFALSE )
\r
1980 *( pusChecksum ) = usChecksum;
\r
1982 #if( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
1983 else if( ( xOutgoingPacket == pdFALSE ) && ( usChecksum != ipCORRECT_CRC ) )
\r
1985 FreeRTOS_debug_printf( ( "usGenerateProtocolChecksum[%s]: ID %04X: from %lxip to %lxip bad crc: %04X\n",
\r
1987 FreeRTOS_ntohs( pxIPPacket->xIPHeader.usIdentification ),
\r
1988 FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulSourceIPAddress ),
\r
1989 FreeRTOS_ntohl( pxIPPacket->xIPHeader.ulDestinationIPAddress ),
\r
1990 FreeRTOS_ntohs( *pusChecksum ) ) );
\r
1992 #endif /* ipconfigHAS_DEBUG_PRINTF != 0 */
\r
1994 return usChecksum;
\r
1996 /*-----------------------------------------------------------*/
\r
1999 * This method generates a checksum for a given IPv4 header, per RFC791 (page 14).
\r
2000 * The checksum algorithm is decribed as:
\r
2001 * "[T]he 16 bit one's complement of the one's complement sum of all 16 bit words in the
\r
2002 * header. For purposes of computing the checksum, the value of the checksum field is zero."
\r
2004 * In a nutshell, that means that each 16-bit 'word' must be summed, after which
\r
2005 * the number of 'carries' (overflows) is added to the result. If that addition
\r
2006 * produces an overflow, that 'carry' must also be added to the final result. The final checksum
\r
2007 * should be the bitwise 'not' (ones-complement) of the result if the packet is
\r
2008 * meant to be transmitted, but this method simply returns the raw value, probably
\r
2009 * because when a packet is received, the checksum is verified by checking that
\r
2010 * ((received & calculated) == 0) without applying a bitwise 'not' to the 'calculated' checksum.
\r
2012 * This logic is optimized for microcontrollers which have limited resources, so the logic looks odd.
\r
2013 * It iterates over the full range of 16-bit words, but it does so by processing several 32-bit
\r
2014 * words at once whenever possible. Its first step is to align the memory pointer to a 32-bit boundary,
\r
2015 * after which it runs a fast loop to process multiple 32-bit words at once and adding their 'carries'.
\r
2016 * Finally, it finishes up by processing any remaining 16-bit words, and adding up all of the 'carries'.
\r
2017 * With 32-bit arithmetic, the number of 16-bit 'carries' produced by sequential additions can be found
\r
2018 * by looking at the 16 most-significant bits of the 32-bit integer, since a 32-bit int will continue
\r
2019 * counting up instead of overflowing after 16 bits. That is why the actual checksum calculations look like:
\r
2020 * union.u32 = ( uint32_t ) union.u16[ 0 ] + union.u16[ 1 ];
\r
2023 * ulSum: This argument provides a value to initialize the progressive summation
\r
2024 * of the header's values to. It is often 0, but protocols like TCP or UDP
\r
2025 * can have pseudo-header fields which need to be included in the checksum.
\r
2026 * pucNextData: This argument contains the address of the first byte which this
\r
2027 * method should process. The method's memory iterator is initialized to this value.
\r
2028 * uxDataLengthBytes: This argument contains the number of bytes that this method
\r
2031 uint16_t usGenerateChecksum( uint32_t ulSum, const uint8_t * pucNextData, size_t uxDataLengthBytes )
\r
2033 xUnion32 xSum2, xSum, xTerm;
\r
2034 xUnionPtr xSource; /* Points to first byte */
\r
2035 xUnionPtr xLastSource; /* Points to last byte plus one */
\r
2036 uint32_t ulAlignBits, ulCarry = 0ul;
\r
2038 /* Small MCUs often spend up to 30% of the time doing checksum calculations
\r
2039 This function is optimised for 32-bit CPUs; Each time it will try to fetch
\r
2040 32-bits, sums it with an accumulator and counts the number of carries. */
\r
2042 /* Swap the input (little endian platform only). */
\r
2043 xSum.u32 = FreeRTOS_ntohs( ulSum );
\r
2046 xSource.u8ptr = ( uint8_t * ) pucNextData;
\r
2047 ulAlignBits = ( ( ( uint32_t ) pucNextData ) & 0x03u ); /* gives 0, 1, 2, or 3 */
\r
2049 /* If byte (8-bit) aligned... */
\r
2050 if( ( ( ulAlignBits & 1ul ) != 0ul ) && ( uxDataLengthBytes >= ( size_t ) 1 ) )
\r
2052 xTerm.u8[ 1 ] = *( xSource.u8ptr );
\r
2053 ( xSource.u8ptr )++;
\r
2054 uxDataLengthBytes--;
\r
2055 /* Now xSource is word (16-bit) aligned. */
\r
2058 /* If half-word (16-bit) aligned... */
\r
2059 if( ( ( ulAlignBits == 1u ) || ( ulAlignBits == 2u ) ) && ( uxDataLengthBytes >= 2u ) )
\r
2061 xSum.u32 += *(xSource.u16ptr);
\r
2062 ( xSource.u16ptr )++;
\r
2063 uxDataLengthBytes -= 2u;
\r
2064 /* Now xSource is word (32-bit) aligned. */
\r
2067 /* Word (32-bit) aligned, do the most part. */
\r
2068 xLastSource.u32ptr = ( xSource.u32ptr + ( uxDataLengthBytes / 4u ) ) - 3u;
\r
2070 /* In this loop, four 32-bit additions will be done, in total 16 bytes.
\r
2071 Indexing with constants (0,1,2,3) gives faster code than using
\r
2072 post-increments. */
\r
2073 while( xSource.u32ptr < xLastSource.u32ptr )
\r
2075 /* Use a secondary Sum2, just to see if the addition produced an
\r
2077 xSum2.u32 = xSum.u32 + xSource.u32ptr[ 0 ];
\r
2078 if( xSum2.u32 < xSum.u32 )
\r
2083 /* Now add the secondary sum to the major sum, and remember if there was
\r
2085 xSum.u32 = xSum2.u32 + xSource.u32ptr[ 1 ];
\r
2086 if( xSum2.u32 > xSum.u32 )
\r
2091 /* And do the same trick once again for indexes 2 and 3 */
\r
2092 xSum2.u32 = xSum.u32 + xSource.u32ptr[ 2 ];
\r
2093 if( xSum2.u32 < xSum.u32 )
\r
2098 xSum.u32 = xSum2.u32 + xSource.u32ptr[ 3 ];
\r
2100 if( xSum2.u32 > xSum.u32 )
\r
2105 /* And finally advance the pointer 4 * 4 = 16 bytes. */
\r
2106 xSource.u32ptr += 4;
\r
2109 /* Now add all carries. */
\r
2110 xSum.u32 = ( uint32_t )xSum.u16[ 0 ] + xSum.u16[ 1 ] + ulCarry;
\r
2112 uxDataLengthBytes %= 16u;
\r
2113 xLastSource.u8ptr = ( uint8_t * ) ( xSource.u8ptr + ( uxDataLengthBytes & ~( ( size_t ) 1 ) ) );
\r
2115 /* Half-word aligned. */
\r
2116 while( xSource.u16ptr < xLastSource.u16ptr )
\r
2118 /* At least one more short. */
\r
2119 xSum.u32 += xSource.u16ptr[ 0 ];
\r
2123 if( ( uxDataLengthBytes & ( size_t ) 1 ) != 0u ) /* Maybe one more ? */
\r
2125 xTerm.u8[ 0 ] = xSource.u8ptr[ 0 ];
\r
2127 xSum.u32 += xTerm.u32;
\r
2129 /* Now add all carries again. */
\r
2130 xSum.u32 = ( uint32_t ) xSum.u16[ 0 ] + xSum.u16[ 1 ];
\r
2132 /* The previous summation might have given a 16-bit carry. */
\r
2133 xSum.u32 = ( uint32_t ) xSum.u16[ 0 ] + xSum.u16[ 1 ];
\r
2135 if( ( ulAlignBits & 1u ) != 0u )
\r
2137 /* Quite unlikely, but pucNextData might be non-aligned, which would
\r
2138 mean that a checksum is calculated starting at an odd position. */
\r
2139 xSum.u32 = ( ( xSum.u32 & 0xffu ) << 8 ) | ( ( xSum.u32 & 0xff00u ) >> 8 );
\r
2142 /* swap the output (little endian platform only). */
\r
2143 return FreeRTOS_htons( ( (uint16_t) xSum.u32 ) );
\r
2145 /*-----------------------------------------------------------*/
\r
2147 void vReturnEthernetFrame( NetworkBufferDescriptor_t * pxNetworkBuffer, BaseType_t xReleaseAfterSend )
\r
2149 EthernetHeader_t *pxEthernetHeader;
\r
2151 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
2152 NetworkBufferDescriptor_t *pxNewBuffer;
\r
2155 #if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
\r
2157 if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )
\r
2159 BaseType_t xIndex;
\r
2161 FreeRTOS_printf( ( "vReturnEthernetFrame: length %lu\n", ( uint32_t )pxNetworkBuffer->xDataLength ) );
\r
2162 for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
\r
2164 pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
\r
2166 pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
\r
2171 #if( ipconfigZERO_COPY_TX_DRIVER != 0 )
\r
2173 if( xReleaseAfterSend == pdFALSE )
\r
2175 pxNewBuffer = pxDuplicateNetworkBufferWithDescriptor( pxNetworkBuffer, ( BaseType_t ) pxNetworkBuffer->xDataLength );
\r
2176 xReleaseAfterSend = pdTRUE;
\r
2177 pxNetworkBuffer = pxNewBuffer;
\r
2180 if( pxNetworkBuffer != NULL )
\r
2183 pxEthernetHeader = ( EthernetHeader_t * ) ( pxNetworkBuffer->pucEthernetBuffer );
\r
2185 /* Swap source and destination MAC addresses. */
\r
2186 memcpy( ( void * ) &( pxEthernetHeader->xDestinationAddress ), ( void * ) &( pxEthernetHeader->xSourceAddress ), sizeof( pxEthernetHeader->xDestinationAddress ) );
\r
2187 memcpy( ( void * ) &( pxEthernetHeader->xSourceAddress) , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
\r
2190 xNetworkInterfaceOutput( pxNetworkBuffer, xReleaseAfterSend );
\r
2193 /*-----------------------------------------------------------*/
\r
2195 uint32_t FreeRTOS_GetIPAddress( void )
\r
2197 /* Returns the IP address of the NIC. */
\r
2198 return *ipLOCAL_IP_ADDRESS_POINTER;
\r
2200 /*-----------------------------------------------------------*/
\r
2202 void FreeRTOS_SetIPAddress( uint32_t ulIPAddress )
\r
2204 /* Sets the IP address of the NIC. */
\r
2205 *ipLOCAL_IP_ADDRESS_POINTER = ulIPAddress;
\r
2207 /*-----------------------------------------------------------*/
\r
2209 uint32_t FreeRTOS_GetGatewayAddress( void )
\r
2211 return xNetworkAddressing.ulGatewayAddress;
\r
2213 /*-----------------------------------------------------------*/
\r
2215 uint32_t FreeRTOS_GetDNSServerAddress( void )
\r
2217 return xNetworkAddressing.ulDNSServerAddress;
\r
2219 /*-----------------------------------------------------------*/
\r
2221 uint32_t FreeRTOS_GetNetmask( void )
\r
2223 return xNetworkAddressing.ulNetMask;
\r
2225 /*-----------------------------------------------------------*/
\r
2227 void FreeRTOS_UpdateMACAddress( const uint8_t ucMACAddress[ipMAC_ADDRESS_LENGTH_BYTES] )
\r
2229 /* Copy the MAC address at the start of the default packet header fragment. */
\r
2230 memcpy( ( void * )ipLOCAL_MAC_ADDRESS, ( void * )ucMACAddress, ( size_t )ipMAC_ADDRESS_LENGTH_BYTES );
\r
2232 /*-----------------------------------------------------------*/
\r
2234 const uint8_t * FreeRTOS_GetMACAddress( void )
\r
2236 return ipLOCAL_MAC_ADDRESS;
\r
2238 /*-----------------------------------------------------------*/
\r
2240 void FreeRTOS_SetNetmask ( uint32_t ulNetmask )
\r
2242 xNetworkAddressing.ulNetMask = ulNetmask;
\r
2244 /*-----------------------------------------------------------*/
\r
2246 void FreeRTOS_SetGatewayAddress ( uint32_t ulGatewayAddress )
\r
2248 xNetworkAddressing.ulGatewayAddress = ulGatewayAddress;
\r
2250 /*-----------------------------------------------------------*/
\r
2252 #if( ipconfigUSE_DHCP == 1 )
\r
2253 void vIPSetDHCPTimerEnableState( BaseType_t xEnableState )
\r
2255 if( xEnableState != pdFALSE )
\r
2257 xDHCPTimer.bActive = pdTRUE_UNSIGNED;
\r
2261 xDHCPTimer.bActive = pdFALSE_UNSIGNED;
\r
2264 #endif /* ipconfigUSE_DHCP */
\r
2265 /*-----------------------------------------------------------*/
\r
2267 #if( ipconfigUSE_DHCP == 1 )
\r
2268 void vIPReloadDHCPTimer( uint32_t ulLeaseTime )
\r
2270 prvIPTimerReload( &xDHCPTimer, ulLeaseTime );
\r
2272 #endif /* ipconfigUSE_DHCP */
\r
2273 /*-----------------------------------------------------------*/
\r
2275 #if( ipconfigDNS_USE_CALLBACKS == 1 )
\r
2276 void vIPSetDnsTimerEnableState( BaseType_t xEnableState )
\r
2278 if( xEnableState != 0 )
\r
2280 xDNSTimer.bActive = pdTRUE;
\r
2284 xDNSTimer.bActive = pdFALSE;
\r
2287 #endif /* ipconfigUSE_DHCP */
\r
2288 /*-----------------------------------------------------------*/
\r
2290 #if( ipconfigDNS_USE_CALLBACKS != 0 )
\r
2291 void vIPReloadDNSTimer( uint32_t ulCheckTime )
\r
2293 prvIPTimerReload( &xDNSTimer, ulCheckTime );
\r
2295 #endif /* ipconfigDNS_USE_CALLBACKS != 0 */
\r
2296 /*-----------------------------------------------------------*/
\r
2298 BaseType_t xIPIsNetworkTaskReady( void )
\r
2300 return xIPTaskInitialised;
\r
2302 /*-----------------------------------------------------------*/
\r
2304 BaseType_t FreeRTOS_IsNetworkUp( void )
\r
2306 return xNetworkUp;
\r
2308 /*-----------------------------------------------------------*/
\r
2310 #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 )
\r
2311 UBaseType_t uxGetMinimumIPQueueSpace( void )
\r
2313 return uxQueueMinimumSpace;
\r
2316 /*-----------------------------------------------------------*/
\r