|
285 | 285 | { |
286 | 286 | BaseType_t x; |
287 | 287 | BaseType_t xFreeEntry = -1, xEntryFound = -1; |
| 288 | + BaseType_t xOldestValue = ipconfigMAX_ARP_AGE + 1; |
| 289 | + BaseType_t xOldestEntry = 0; |
288 | 290 |
|
289 | 291 | /* For each entry in the ND cache table. */ |
290 | 292 | for( x = 0; x < ipconfigND_CACHE_ENTRIES; x++ ) |
|
304 | 306 | else |
305 | 307 | { |
306 | 308 | /* Entry is valid but the IP-address doesn't match. */ |
| 309 | + |
| 310 | + /* Keep track of the oldest entry in case we need to overwrite it. The problem we are trying to avoid is |
| 311 | + * that there may be a queued packet in pxARPWaitingNetworkBuffer and we may have just received the |
| 312 | + * neighbor advertisement needed for that packet. If we don't store this network advertisement in cache, |
| 313 | + * the parting of the frame from pxARPWaitingNetworkBuffer will cause the sending of neighbor solicitation |
| 314 | + * and stores the frame in pxARPWaitingNetworkBuffer. This becomes a vicious circle with thousands of |
| 315 | + * neighbor solicitation/advertisement packets going back and forth because the ND cache is full. |
| 316 | + * Overwriting the oldest cache entry is not a fool-proof solution, but it's something. */ |
| 317 | + if( xNDCache[ x ].ucAge < xOldestValue ) |
| 318 | + { |
| 319 | + xOldestValue = xNDCache[ x ].ucAge; |
| 320 | + xOldestEntry = x; |
| 321 | + } |
307 | 322 | } |
308 | 323 | } |
309 | 324 |
|
310 | 325 | if( xEntryFound < 0 ) |
311 | 326 | { |
312 | 327 | /* The IP-address was not found, use the first free location. */ |
313 | | - xEntryFound = xFreeEntry; |
| 328 | + if( xFreeEntry >= 0 ) |
| 329 | + { |
| 330 | + xEntryFound = xFreeEntry; |
| 331 | + } |
| 332 | + else |
| 333 | + { |
| 334 | + /* No free location. Overwrite the oldest. */ |
| 335 | + xEntryFound = xOldestEntry; |
| 336 | + FreeRTOS_printf( ( "vNDRefreshCacheEntry: Cache FULL! Overwriting oldest entry %i with %02X-%02X-%02X-%02X-%02X-%02X\n", ( int ) xEntryFound, pxMACAddress->ucBytes[ 0 ], pxMACAddress->ucBytes[ 1 ], pxMACAddress->ucBytes[ 2 ], pxMACAddress->ucBytes[ 3 ], pxMACAddress->ucBytes[ 4 ], pxMACAddress->ucBytes[ 5 ] ) ); |
| 337 | + } |
314 | 338 | } |
315 | 339 |
|
316 | | - if( xEntryFound >= 0 ) |
317 | | - { |
318 | | - /* Copy the IP-address. */ |
319 | | - ( void ) memcpy( xNDCache[ xEntryFound ].xIPAddress.ucBytes, pxIPAddress->ucBytes, ipSIZE_OF_IPv6_ADDRESS ); |
320 | | - /* Copy the MAC-address. */ |
321 | | - ( void ) memcpy( xNDCache[ xEntryFound ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( MACAddress_t ) ); |
322 | | - xNDCache[ xEntryFound ].pxEndPoint = pxEndPoint; |
323 | | - xNDCache[ xEntryFound ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE; |
324 | | - xNDCache[ xEntryFound ].ucValid = ( uint8_t ) pdTRUE; |
325 | | - } |
326 | | - else |
327 | | - { |
328 | | - FreeRTOS_printf( ( "vNDRefreshCacheEntry: %pip not found\n", ( void * ) pxIPAddress->ucBytes ) ); |
329 | | - } |
| 340 | + /* At this point, xEntryFound is always a valid index. */ |
| 341 | + /* Copy the IP-address. */ |
| 342 | + ( void ) memcpy( xNDCache[ xEntryFound ].xIPAddress.ucBytes, pxIPAddress->ucBytes, ipSIZE_OF_IPv6_ADDRESS ); |
| 343 | + /* Copy the MAC-address. */ |
| 344 | + ( void ) memcpy( xNDCache[ xEntryFound ].xMACAddress.ucBytes, pxMACAddress->ucBytes, sizeof( MACAddress_t ) ); |
| 345 | + xNDCache[ xEntryFound ].pxEndPoint = pxEndPoint; |
| 346 | + xNDCache[ xEntryFound ].ucAge = ( uint8_t ) ipconfigMAX_ARP_AGE; |
| 347 | + xNDCache[ xEntryFound ].ucValid = ( uint8_t ) pdTRUE; |
330 | 348 | } |
331 | 349 | /*-----------------------------------------------------------*/ |
332 | 350 |
|
|
482 | 500 | char pcBuffer[ 40 ]; |
483 | 501 |
|
484 | 502 | /* Loop through each entry in the ND cache. */ |
485 | | - for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ ) |
| 503 | + for( x = 0; x < ipconfigND_CACHE_ENTRIES; x++ ) |
486 | 504 | { |
487 | 505 | if( xNDCache[ x ].ucValid != ( uint8_t ) 0U ) |
488 | 506 | { |
|
0 commit comments