2 * FreeRTOS+TCP V2.0.3
\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
30 /* FreeRTOS includes. */
\r
31 #include "FreeRTOS.h"
\r
36 /* FreeRTOS+TCP includes. */
\r
37 #include "FreeRTOS_IP.h"
\r
38 #include "FreeRTOS_Sockets.h"
\r
39 #include "FreeRTOS_IP_Private.h"
\r
40 #include "FreeRTOS_ARP.h"
\r
41 #include "FreeRTOS_UDP_IP.h"
\r
42 #include "FreeRTOS_DHCP.h"
\r
43 #if( ipconfigUSE_LLMNR == 1 )
\r
44 #include "FreeRTOS_DNS.h"
\r
45 #endif /* ipconfigUSE_LLMNR */
\r
46 #include "NetworkInterface.h"
\r
47 #include "NetworkBufferManagement.h"
\r
50 /* When the age of an entry in the ARP table reaches this value (it counts down
\r
51 to zero, so this is an old entry) an ARP request will be sent to see if the
\r
52 entry is still valid and can therefore be refreshed. */
\r
53 #define arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST ( 3 )
\r
55 /* The time between gratuitous ARPs. */
\r
56 #ifndef arpGRATUITOUS_ARP_PERIOD
\r
57 #define arpGRATUITOUS_ARP_PERIOD ( pdMS_TO_TICKS( 20000 ) )
\r
60 /*-----------------------------------------------------------*/
\r
63 * Lookup an MAC address in the ARP cache from the IP address.
\r
65 static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress_t * const pxMACAddress );
\r
67 /*-----------------------------------------------------------*/
\r
69 /* The ARP cache. */
\r
70 static ARPCacheRow_t xARPCache[ ipconfigARP_CACHE_ENTRIES ];
\r
72 /* The time at which the last gratuitous ARP was sent. Gratuitous ARPs are used
\r
73 to ensure ARP tables are up to date and to detect IP address conflicts. */
\r
74 static TickType_t xLastGratuitousARPTime = ( TickType_t ) 0;
\r
77 * IP-clash detection is currently only used internally. When DHCP doesn't respond, the
\r
78 * driver can try out a random LinkLayer IP address (169.254.x.x). It will send out a
\r
79 * gratuitos ARP message and, after a period of time, check the variables here below:
\r
81 #if( ipconfigARP_USE_CLASH_DETECTION != 0 )
\r
82 /* Becomes non-zero if another device responded to a gratuitos ARP message. */
\r
83 BaseType_t xARPHadIPClash;
\r
84 /* MAC-address of the other device containing the same IP-address. */
\r
85 MACAddress_t xARPClashMacAddress;
\r
86 #endif /* ipconfigARP_USE_CLASH_DETECTION */
\r
88 /* Part of the Ethernet and ARP headers are always constant when sending an IPv4
\r
89 ARP packet. This array defines the constant parts, allowing this part of the
\r
90 packet to be filled in using a simple memcpy() instead of individual writes. */
\r
91 static const uint8_t xDefaultPartARPPacketHeader[] =
\r
93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* Ethernet destination address. */
\r
94 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* Ethernet source address. */
\r
95 0x08, 0x06, /* Ethernet frame type (ipARP_FRAME_TYPE). */
\r
96 0x00, 0x01, /* usHardwareType (ipARP_HARDWARE_TYPE_ETHERNET). */
\r
97 0x08, 0x00, /* usProtocolType. */
\r
98 ipMAC_ADDRESS_LENGTH_BYTES, /* ucHardwareAddressLength. */
\r
99 ipIP_ADDRESS_LENGTH_BYTES, /* ucProtocolAddressLength. */
\r
100 0x00, 0x01, /* usOperation (ipARP_REQUEST). */
\r
101 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* xSenderHardwareAddress. */
\r
102 0x00, 0x00, 0x00, 0x00, /* ulSenderProtocolAddress. */
\r
103 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* xTargetHardwareAddress. */
\r
106 /*-----------------------------------------------------------*/
\r
108 eFrameProcessingResult_t eARPProcessPacket( ARPPacket_t * const pxARPFrame )
\r
110 eFrameProcessingResult_t eReturn = eReleaseBuffer;
\r
111 ARPHeader_t *pxARPHeader;
\r
112 uint32_t ulTargetProtocolAddress, ulSenderProtocolAddress;
\r
114 pxARPHeader = &( pxARPFrame->xARPHeader );
\r
116 /* The field ulSenderProtocolAddress is badly aligned, copy byte-by-byte. */
\r
117 memcpy( ( void *)&( ulSenderProtocolAddress ), ( void * )pxARPHeader->ucSenderProtocolAddress, sizeof( ulSenderProtocolAddress ) );
\r
118 /* The field ulTargetProtocolAddress is well-aligned, a 32-bits copy. */
\r
119 ulTargetProtocolAddress = pxARPHeader->ulTargetProtocolAddress;
\r
121 traceARP_PACKET_RECEIVED();
\r
123 /* Don't do anything if the local IP address is zero because
\r
124 that means a DHCP request has not completed. */
\r
125 if( *ipLOCAL_IP_ADDRESS_POINTER != 0UL )
\r
127 switch( pxARPHeader->usOperation )
\r
129 case ipARP_REQUEST :
\r
130 /* The packet contained an ARP request. Was it for the IP
\r
131 address of the node running this code? */
\r
132 if( ulTargetProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )
\r
134 iptraceSENDING_ARP_REPLY( ulSenderProtocolAddress );
\r
136 /* The request is for the address of this node. Add the
\r
137 entry into the ARP cache, or refresh the entry if it
\r
139 vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );
\r
141 /* Generate a reply payload in the same buffer. */
\r
142 pxARPHeader->usOperation = ( uint16_t ) ipARP_REPLY;
\r
143 if( ulTargetProtocolAddress == ulSenderProtocolAddress )
\r
145 /* A double IP address is detected! */
\r
146 /* Give the sources MAC address the value of the broadcast address, will be swapped later */
\r
147 memcpy( pxARPFrame->xEthernetHeader.xSourceAddress.ucBytes, xBroadcastMACAddress.ucBytes, sizeof( xBroadcastMACAddress ) );
\r
148 memset( pxARPHeader->xTargetHardwareAddress.ucBytes, '\0', sizeof( MACAddress_t ) );
\r
149 pxARPHeader->ulTargetProtocolAddress = 0UL;
\r
153 memcpy( pxARPHeader->xTargetHardwareAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( MACAddress_t ) );
\r
154 pxARPHeader->ulTargetProtocolAddress = ulSenderProtocolAddress;
\r
156 memcpy( pxARPHeader->xSenderHardwareAddress.ucBytes, ( void * ) ipLOCAL_MAC_ADDRESS, sizeof( MACAddress_t ) );
\r
157 memcpy( ( void* )pxARPHeader->ucSenderProtocolAddress, ( void* )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPHeader->ucSenderProtocolAddress ) );
\r
159 eReturn = eReturnEthernetFrame;
\r
164 iptracePROCESSING_RECEIVED_ARP_REPLY( ulTargetProtocolAddress );
\r
165 vARPRefreshCacheEntry( &( pxARPHeader->xSenderHardwareAddress ), ulSenderProtocolAddress );
\r
166 /* Process received ARP frame to see if there is a clash. */
\r
167 #if( ipconfigARP_USE_CLASH_DETECTION != 0 )
\r
169 if( ulSenderProtocolAddress == *ipLOCAL_IP_ADDRESS_POINTER )
\r
171 xARPHadIPClash = pdTRUE;
\r
172 memcpy( xARPClashMacAddress.ucBytes, pxARPHeader->xSenderHardwareAddress.ucBytes, sizeof( xARPClashMacAddress.ucBytes ) );
\r
175 #endif /* ipconfigARP_USE_CLASH_DETECTION */
\r
186 /*-----------------------------------------------------------*/
\r
188 #if( ipconfigUSE_ARP_REMOVE_ENTRY != 0 )
\r
190 uint32_t ulARPRemoveCacheEntryByMac( const MACAddress_t * pxMACAddress )
\r
193 uint32_t lResult = 0;
\r
195 /* For each entry in the ARP cache table. */
\r
196 for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
\r
198 if( ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) )
\r
200 lResult = xARPCache[ x ].ulIPAddress;
\r
201 memset( &xARPCache[ x ], '\0', sizeof( xARPCache[ x ] ) );
\r
209 #endif /* ipconfigUSE_ARP_REMOVE_ENTRY != 0 */
\r
210 /*-----------------------------------------------------------*/
\r
212 void vARPRefreshCacheEntry( const MACAddress_t * pxMACAddress, const uint32_t ulIPAddress )
\r
214 BaseType_t x, xIpEntry = -1, xMacEntry = -1, xUseEntry = 0;
\r
215 uint8_t ucMinAgeFound = 0U;
\r
217 #if( ipconfigARP_STORES_REMOTE_ADDRESSES == 0 )
\r
218 /* Only process the IP address if it is on the local network.
\r
219 Unless: when '*ipLOCAL_IP_ADDRESS_POINTER' equals zero, the IP-address
\r
220 and netmask are still unknown. */
\r
221 if( ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) ) ||
\r
222 ( *ipLOCAL_IP_ADDRESS_POINTER == 0ul ) )
\r
224 /* If ipconfigARP_STORES_REMOTE_ADDRESSES is non-zero, IP addresses with
\r
225 a different netmask will also be stored. After when replying to a UDP
\r
226 message from a different netmask, the IP address can be looped up and a
\r
227 reply sent. This option is useful for systems with multiple gateways,
\r
228 the reply will surely arrive. If ipconfigARP_STORES_REMOTE_ADDRESSES is
\r
229 zero the the gateway address is the only option. */
\r
233 /* Start with the maximum possible number. */
\r
236 /* For each entry in the ARP cache table. */
\r
237 for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
\r
239 /* Does this line in the cache table hold an entry for the IP
\r
240 address being queried? */
\r
241 if( xARPCache[ x ].ulIPAddress == ulIPAddress )
\r
243 if( pxMACAddress == NULL )
\r
245 /* In case the parameter pxMACAddress is NULL, an entry will be reserved to
\r
246 indicate that there is an outstanding ARP request, This entry will have
\r
247 "ucValid == pdFALSE". */
\r
252 /* See if the MAC-address also matches. */
\r
253 if( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 )
\r
255 /* This function will be called for each received packet
\r
256 As this is by far the most common path the coding standard
\r
257 is relaxed in this case and a return is permitted as an
\r
259 xARPCache[ x ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
\r
260 xARPCache[ x ].ucValid = ( uint8_t ) pdTRUE;
\r
264 /* Found an entry containing ulIPAddress, but the MAC address
\r
265 doesn't match. Might be an entry with ucValid=pdFALSE, waiting
\r
266 for an ARP reply. Still want to see if there is match with the
\r
267 given MAC address.ucBytes. If found, either of the two entries
\r
268 must be cleared. */
\r
271 else if( ( pxMACAddress != NULL ) && ( memcmp( xARPCache[ x ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) ) == 0 ) )
\r
273 /* Found an entry with the given MAC-address, but the IP-address
\r
274 is different. Continue looping to find a possible match with
\r
276 #if( ipconfigARP_STORES_REMOTE_ADDRESSES != 0 )
\r
277 /* If ARP stores the MAC address of IP addresses outside the
\r
278 network, than the MAC address of the gateway should not be
\r
280 BaseType_t bIsLocal[ 2 ];
\r
281 bIsLocal[ 0 ] = ( ( xARPCache[ x ].ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) );
\r
282 bIsLocal[ 1 ] = ( ( ulIPAddress & xNetworkAddressing.ulNetMask ) == ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) );
\r
283 if( bIsLocal[ 0 ] == bIsLocal[ 1 ] )
\r
292 Shouldn't we test for xARPCache[ x ].ucValid == pdFALSE here ? */
\r
293 else if( xARPCache[ x ].ucAge < ucMinAgeFound )
\r
295 /* As the table is traversed, remember the table row that
\r
296 contains the oldest entry (the lowest age count, as ages are
\r
297 decremented to zero) so the row can be re-used if this function
\r
298 needs to add an entry that does not already exist. */
\r
299 ucMinAgeFound = xARPCache[ x ].ucAge;
\r
304 if( xMacEntry >= 0 )
\r
306 xUseEntry = xMacEntry;
\r
308 if( xIpEntry >= 0 )
\r
310 /* Both the MAC address as well as the IP address were found in
\r
311 different locations: clear the entry which matches the
\r
313 memset( &xARPCache[ xIpEntry ], '\0', sizeof( xARPCache[ xIpEntry ] ) );
\r
316 else if( xIpEntry >= 0 )
\r
318 /* An entry containing the IP-address was found, but it had a different MAC address */
\r
319 xUseEntry = xIpEntry;
\r
322 /* If the entry was not found, we use the oldest entry and set the IPaddress */
\r
323 xARPCache[ xUseEntry ].ulIPAddress = ulIPAddress;
\r
325 if( pxMACAddress != NULL )
\r
327 memcpy( xARPCache[ xUseEntry ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( pxMACAddress->ucBytes ) );
\r
329 iptraceARP_TABLE_ENTRY_CREATED( ulIPAddress, (*pxMACAddress) );
\r
330 /* And this entry does not need immediate attention */
\r
331 xARPCache[ xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE;
\r
332 xARPCache[ xUseEntry ].ucValid = ( uint8_t ) pdTRUE;
\r
334 else if( xIpEntry < 0 )
\r
336 xARPCache[ xUseEntry ].ucAge = ( uint8_t ) ipconfigMAX_ARP_RETRANSMISSIONS;
\r
337 xARPCache[ xUseEntry ].ucValid = ( uint8_t ) pdFALSE;
\r
341 /*-----------------------------------------------------------*/
\r
343 #if( ipconfigUSE_ARP_REVERSED_LOOKUP == 1 )
\r
344 eARPLookupResult_t eARPGetCacheEntryByMac( MACAddress_t * const pxMACAddress, uint32_t *pulIPAddress )
\r
347 eARPLookupResult_t eReturn = eARPCacheMiss;
\r
349 /* Loop through each entry in the ARP cache. */
\r
350 for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
\r
352 /* Does this row in the ARP cache table hold an entry for the MAC
\r
353 address being searched? */
\r
354 if( memcmp( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) ) == 0 )
\r
356 *pulIPAddress = xARPCache[ x ].ulIPAddress;
\r
357 eReturn = eARPCacheHit;
\r
364 #endif /* ipconfigUSE_ARP_REVERSED_LOOKUP */
\r
366 /*-----------------------------------------------------------*/
\r
368 eARPLookupResult_t eARPGetCacheEntry( uint32_t *pulIPAddress, MACAddress_t * const pxMACAddress )
\r
370 eARPLookupResult_t eReturn;
\r
371 uint32_t ulAddressToLookup;
\r
373 #if( ipconfigUSE_LLMNR == 1 )
\r
374 if( *pulIPAddress == ipLLMNR_IP_ADDR ) /* Is in network byte order. */
\r
376 /* The LLMNR IP-address has a fixed virtual MAC address. */
\r
377 memcpy( pxMACAddress->ucBytes, xLLMNR_MacAdress.ucBytes, sizeof( MACAddress_t ) );
\r
378 eReturn = eARPCacheHit;
\r
382 if( ( *pulIPAddress == ipBROADCAST_IP_ADDRESS ) || /* Is it the general broadcast address 255.255.255.255? */
\r
383 ( *pulIPAddress == xNetworkAddressing.ulBroadcastAddress ) )/* Or a local broadcast address, eg 192.168.1.255? */
\r
385 /* This is a broadcast so uses the broadcast MAC address. */
\r
386 memcpy( pxMACAddress->ucBytes, xBroadcastMACAddress.ucBytes, sizeof( MACAddress_t ) );
\r
387 eReturn = eARPCacheHit;
\r
389 else if( *ipLOCAL_IP_ADDRESS_POINTER == 0UL )
\r
391 /* The IP address has not yet been assigned, so there is nothing that
\r
393 eReturn = eCantSendPacket;
\r
397 eReturn = eARPCacheMiss;
\r
399 if( ( *pulIPAddress & xNetworkAddressing.ulNetMask ) != ( ( *ipLOCAL_IP_ADDRESS_POINTER ) & xNetworkAddressing.ulNetMask ) )
\r
401 #if( ipconfigARP_STORES_REMOTE_ADDRESSES == 1 )
\r
402 eReturn = prvCacheLookup( *pulIPAddress, pxMACAddress );
\r
404 if( eReturn == eARPCacheHit )
\r
406 /* The stack is configured to store 'remote IP addresses', i.e. addresses
\r
407 belonging to a different the netmask. prvCacheLookup() returned a hit, so
\r
408 the MAC address is known */
\r
413 /* The IP address is off the local network, so look up the
\r
414 hardware address of the router, if any. */
\r
415 if( xNetworkAddressing.ulGatewayAddress != ( uint32_t )0u )
\r
417 ulAddressToLookup = xNetworkAddressing.ulGatewayAddress;
\r
421 ulAddressToLookup = *pulIPAddress;
\r
427 /* The IP address is on the local network, so lookup the requested
\r
428 IP address directly. */
\r
429 ulAddressToLookup = *pulIPAddress;
\r
432 if( eReturn == eARPCacheMiss )
\r
434 if( ulAddressToLookup == 0UL )
\r
436 /* The address is not on the local network, and there is not a
\r
438 eReturn = eCantSendPacket;
\r
442 eReturn = prvCacheLookup( ulAddressToLookup, pxMACAddress );
\r
444 if( eReturn == eARPCacheMiss )
\r
446 /* It might be that the ARP has to go to the gateway. */
\r
447 *pulIPAddress = ulAddressToLookup;
\r
456 /*-----------------------------------------------------------*/
\r
458 static eARPLookupResult_t prvCacheLookup( uint32_t ulAddressToLookup, MACAddress_t * const pxMACAddress )
\r
461 eARPLookupResult_t eReturn = eARPCacheMiss;
\r
463 /* Loop through each entry in the ARP cache. */
\r
464 for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
\r
466 /* Does this row in the ARP cache table hold an entry for the IP address
\r
468 if( xARPCache[ x ].ulIPAddress == ulAddressToLookup )
\r
470 /* A matching valid entry was found. */
\r
471 if( xARPCache[ x ].ucValid == ( uint8_t ) pdFALSE )
\r
473 /* This entry is waiting an ARP reply, so is not valid. */
\r
474 eReturn = eCantSendPacket;
\r
478 /* A valid entry was found. */
\r
479 memcpy( pxMACAddress->ucBytes, xARPCache[ x ].xMACAddress.ucBytes, sizeof( MACAddress_t ) );
\r
480 eReturn = eARPCacheHit;
\r
488 /*-----------------------------------------------------------*/
\r
490 void vARPAgeCache( void )
\r
493 TickType_t xTimeNow;
\r
495 /* Loop through each entry in the ARP cache. */
\r
496 for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
\r
498 /* If the entry is valid (its age is greater than zero). */
\r
499 if( xARPCache[ x ].ucAge > 0U )
\r
501 /* Decrement the age value of the entry in this ARP cache table row.
\r
502 When the age reaches zero it is no longer considered valid. */
\r
503 ( xARPCache[ x ].ucAge )--;
\r
505 /* If the entry is not yet valid, then it is waiting an ARP
\r
506 reply, and the ARP request should be retransmitted. */
\r
507 if( xARPCache[ x ].ucValid == ( uint8_t ) pdFALSE )
\r
509 FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress );
\r
511 else if( xARPCache[ x ].ucAge <= ( uint8_t ) arpMAX_ARP_AGE_BEFORE_NEW_ARP_REQUEST )
\r
513 /* This entry will get removed soon. See if the MAC address is
\r
514 still valid to prevent this happening. */
\r
515 iptraceARP_TABLE_ENTRY_WILL_EXPIRE( xARPCache[ x ].ulIPAddress );
\r
516 FreeRTOS_OutputARPRequest( xARPCache[ x ].ulIPAddress );
\r
520 /* The age has just ticked down, with nothing to do. */
\r
523 if( xARPCache[ x ].ucAge == 0u )
\r
525 /* The entry is no longer valid. Wipe it out. */
\r
526 iptraceARP_TABLE_ENTRY_EXPIRED( xARPCache[ x ].ulIPAddress );
\r
527 xARPCache[ x ].ulIPAddress = 0UL;
\r
532 xTimeNow = xTaskGetTickCount ();
\r
534 if( ( xLastGratuitousARPTime == ( TickType_t ) 0 ) || ( ( xTimeNow - xLastGratuitousARPTime ) > ( TickType_t ) arpGRATUITOUS_ARP_PERIOD ) )
\r
536 FreeRTOS_OutputARPRequest( *ipLOCAL_IP_ADDRESS_POINTER );
\r
537 xLastGratuitousARPTime = xTimeNow;
\r
540 /*-----------------------------------------------------------*/
\r
542 void vARPSendGratuitous( void )
\r
544 /* Setting xLastGratuitousARPTime to 0 will force a gratuitous ARP the next
\r
545 time vARPAgeCache() is called. */
\r
546 xLastGratuitousARPTime = ( TickType_t ) 0;
\r
548 /* Let the IP-task call vARPAgeCache(). */
\r
549 xSendEventToIPTask( eARPTimerEvent );
\r
552 /*-----------------------------------------------------------*/
\r
553 void FreeRTOS_OutputARPRequest( uint32_t ulIPAddress )
\r
555 NetworkBufferDescriptor_t *pxNetworkBuffer;
\r
557 /* This is called from the context of the IP event task, so a block time
\r
558 must not be used. */
\r
559 pxNetworkBuffer = pxGetNetworkBufferWithDescriptor( sizeof( ARPPacket_t ), ( TickType_t ) 0 );
\r
561 if( pxNetworkBuffer != NULL )
\r
563 pxNetworkBuffer->ulIPAddress = ulIPAddress;
\r
564 vARPGenerateRequestPacket( pxNetworkBuffer );
\r
566 #if defined( ipconfigETHERNET_MINIMUM_PACKET_BYTES )
\r
568 if( pxNetworkBuffer->xDataLength < ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES )
\r
572 for( xIndex = ( BaseType_t ) pxNetworkBuffer->xDataLength; xIndex < ( BaseType_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES; xIndex++ )
\r
574 pxNetworkBuffer->pucEthernetBuffer[ xIndex ] = 0u;
\r
576 pxNetworkBuffer->xDataLength = ( size_t ) ipconfigETHERNET_MINIMUM_PACKET_BYTES;
\r
581 xNetworkInterfaceOutput( pxNetworkBuffer, pdTRUE );
\r
585 void vARPGenerateRequestPacket( NetworkBufferDescriptor_t * const pxNetworkBuffer )
\r
587 ARPPacket_t *pxARPPacket;
\r
589 pxARPPacket = ( ARPPacket_t * ) pxNetworkBuffer->pucEthernetBuffer;
\r
591 /* memcpy the const part of the header information into the correct
\r
592 location in the packet. This copies:
\r
593 xEthernetHeader.ulDestinationAddress
\r
594 xEthernetHeader.usFrameType;
\r
595 xARPHeader.usHardwareType;
\r
596 xARPHeader.usProtocolType;
\r
597 xARPHeader.ucHardwareAddressLength;
\r
598 xARPHeader.ucProtocolAddressLength;
\r
599 xARPHeader.usOperation;
\r
600 xARPHeader.xTargetHardwareAddress;
\r
602 memcpy( ( void * ) &( pxARPPacket->xEthernetHeader ), ( void * ) xDefaultPartARPPacketHeader, sizeof( xDefaultPartARPPacketHeader ) );
\r
603 memcpy( ( void * ) pxARPPacket->xEthernetHeader.xSourceAddress.ucBytes , ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
\r
604 memcpy( ( void * ) pxARPPacket->xARPHeader.xSenderHardwareAddress.ucBytes, ( void * ) ipLOCAL_MAC_ADDRESS, ( size_t ) ipMAC_ADDRESS_LENGTH_BYTES );
\r
606 memcpy( ( void* )pxARPPacket->xARPHeader.ucSenderProtocolAddress, ( void* )ipLOCAL_IP_ADDRESS_POINTER, sizeof( pxARPPacket->xARPHeader.ucSenderProtocolAddress ) );
\r
607 pxARPPacket->xARPHeader.ulTargetProtocolAddress = pxNetworkBuffer->ulIPAddress;
\r
609 pxNetworkBuffer->xDataLength = sizeof( ARPPacket_t );
\r
611 iptraceCREATING_ARP_REQUEST( pxNetworkBuffer->ulIPAddress );
\r
613 /*-----------------------------------------------------------*/
\r
615 void FreeRTOS_ClearARP( void )
\r
617 memset( xARPCache, '\0', sizeof( xARPCache ) );
\r
619 /*-----------------------------------------------------------*/
\r
621 #if( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 )
\r
623 void FreeRTOS_PrintARPCache( void )
\r
625 BaseType_t x, xCount = 0;
\r
627 /* Loop through each entry in the ARP cache. */
\r
628 for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ )
\r
630 if( ( xARPCache[ x ].ulIPAddress != 0ul ) && ( xARPCache[ x ].ucAge > 0U ) )
\r
632 /* See if the MAC-address also matches, and we're all happy */
\r
633 FreeRTOS_printf( ( "Arp %2ld: %3u - %16lxip : %02x:%02x:%02x : %02x:%02x:%02x\n",
\r
635 xARPCache[ x ].ucAge,
\r
636 xARPCache[ x ].ulIPAddress,
\r
637 xARPCache[ x ].xMACAddress.ucBytes[0],
\r
638 xARPCache[ x ].xMACAddress.ucBytes[1],
\r
639 xARPCache[ x ].xMACAddress.ucBytes[2],
\r
640 xARPCache[ x ].xMACAddress.ucBytes[3],
\r
641 xARPCache[ x ].xMACAddress.ucBytes[4],
\r
642 xARPCache[ x ].xMACAddress.ucBytes[5] ) );
\r
647 FreeRTOS_printf( ( "Arp has %ld entries\n", xCount ) );
\r
650 #endif /* ( ipconfigHAS_PRINTF != 0 ) || ( ipconfigHAS_DEBUG_PRINTF != 0 ) */
\r