Second phase of address cache refactoring:
1. Added time to live functionality 2. Added option of partial cache init on reset to reduce traffic for controllers that can preserve RAM over power cycle/reset. 3. Can now put new entries in the cache even if it is full - entry nearest to expiry is dropped to make room.
This commit is contained in:
@@ -411,6 +411,7 @@ int main(
|
|||||||
putchar('.'); /* Just to show that time is passing... */
|
putchar('.'); /* Just to show that time is passing... */
|
||||||
last_seconds = current_seconds;
|
last_seconds = current_seconds;
|
||||||
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
||||||
|
address_cache_timer(current_seconds - last_seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(_kbhit()) {
|
if(_kbhit()) {
|
||||||
@@ -442,8 +443,10 @@ int main(
|
|||||||
npdu_handler(&src, &Rx_Buf[0], pdu_len);
|
npdu_handler(&src, &Rx_Buf[0], pdu_len);
|
||||||
}
|
}
|
||||||
/* at least one second has passed */
|
/* at least one second has passed */
|
||||||
if (current_seconds != last_seconds)
|
if (current_seconds != last_seconds) {
|
||||||
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
tsm_timer_milliseconds(((current_seconds - last_seconds) * 1000));
|
||||||
|
address_cache_timer(current_seconds - last_seconds);
|
||||||
|
}
|
||||||
if (Error_Detected)
|
if (Error_Detected)
|
||||||
break;
|
break;
|
||||||
/* wait until the device is bound, or timeout and quit */
|
/* wait until the device is bound, or timeout and quit */
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ extern "C" {
|
|||||||
void address_init(
|
void address_init(
|
||||||
void);
|
void);
|
||||||
|
|
||||||
|
void address_init_partial(
|
||||||
|
void);
|
||||||
|
|
||||||
void address_add(
|
void address_add(
|
||||||
uint32_t device_id,
|
uint32_t device_id,
|
||||||
unsigned max_apdu,
|
unsigned max_apdu,
|
||||||
@@ -90,6 +93,14 @@ extern "C" {
|
|||||||
uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
unsigned apdu_len);
|
unsigned apdu_len);
|
||||||
|
|
||||||
|
void address_set_device_TTL(
|
||||||
|
uint32_t device_id,
|
||||||
|
uint32_t TimeOut,
|
||||||
|
bool StaticFlag);
|
||||||
|
|
||||||
|
void address_cache_timer(
|
||||||
|
uint16_t uSeconds);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /* __cplusplus */
|
#endif /* __cplusplus */
|
||||||
|
|||||||
+235
-21
@@ -56,12 +56,18 @@ static struct Address_Cache_Entry {
|
|||||||
|
|
||||||
/* State flags for cache entries */
|
/* State flags for cache entries */
|
||||||
|
|
||||||
#define BAC_ADDR_IN_USE 1 /* Address cache entry in use */
|
#define BAC_ADDR_IN_USE 1 /* Address cache entry in use */
|
||||||
#define BAC_ADDR_BIND_REQ 2 /* Bind request outstanding for entry */
|
#define BAC_ADDR_BIND_REQ 2 /* Bind request outstanding for entry */
|
||||||
#define BAC_ADDR_STATIC 4 /* Static address mapping - does not expire */
|
#define BAC_ADDR_STATIC 4 /* Static address mapping - does not expire */
|
||||||
#define BAC_ADDR_SHORT_TTL 8 /* Oppertunistaclly added address with short TTL */
|
#define BAC_ADDR_SHORT_TTL 8 /* Oppertunistaclly added address with short TTL */
|
||||||
|
#define BAC_ADDR_RESERVED 128 /* Freed up but held for caller to fill */
|
||||||
|
|
||||||
|
#define BAC_ADDR_SECS_1HOUR 3600 /* 60x60 */
|
||||||
|
#define BAC_ADDR_SECS_1DAY 86400 /* 60x60x24 */
|
||||||
|
|
||||||
|
#define BAC_ADDR_LONG_TIME BAC_ADDR_SECS_1DAY
|
||||||
|
#define BAC_ADDR_SHORT_TIME BAC_ADDR_SECS_1HOUR
|
||||||
|
#define BAC_ADDR_FOREVER 0xFFFFFFFF /* Permenant entry */
|
||||||
|
|
||||||
bool address_match(
|
bool address_match(
|
||||||
BACNET_ADDRESS * dest,
|
BACNET_ADDRESS * dest,
|
||||||
@@ -116,6 +122,65 @@ void address_remove_device(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Search the cache for the entry nearest expiry and delete it. Mark the *
|
||||||
|
* entry as reserved with a 1 hour TTL and return a pointer to the reserved *
|
||||||
|
* entry. Will not delete a static entry and returns NULL pointer if no *
|
||||||
|
* entry available to free up. Does not check for free entries as it is *
|
||||||
|
* assumed we are calling this due to the lack of those. *
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
struct Address_Cache_Entry * address_remove_oldest(
|
||||||
|
void)
|
||||||
|
{
|
||||||
|
struct Address_Cache_Entry *pMatch;
|
||||||
|
struct Address_Cache_Entry *pCandidate;
|
||||||
|
uint32_t ulTime;
|
||||||
|
|
||||||
|
pCandidate = NULL;
|
||||||
|
ulTime = BAC_ADDR_FOREVER - 1; /* Longest possible non static time to live */
|
||||||
|
|
||||||
|
/* First pass - try only in use and bound entries */
|
||||||
|
|
||||||
|
pMatch = Address_Cache;
|
||||||
|
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1]) {
|
||||||
|
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ | BAC_ADDR_STATIC)) == BAC_ADDR_IN_USE) {
|
||||||
|
if(pMatch->TimeToLive <= ulTime) { /* Shorter lived entry found */
|
||||||
|
ulTime = pMatch->TimeToLive;
|
||||||
|
pCandidate = pMatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pMatch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pCandidate != NULL) { /* Found something to free up */
|
||||||
|
pCandidate->Flags = BAC_ADDR_RESERVED;
|
||||||
|
pCandidate->TimeToLive = BAC_ADDR_SHORT_TIME; /* only reserve it for a short while */
|
||||||
|
return(pCandidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Second pass - try in use and un bound as last resort */
|
||||||
|
pMatch = Address_Cache;
|
||||||
|
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1]) {
|
||||||
|
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ | BAC_ADDR_STATIC)) == (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) {
|
||||||
|
if(pMatch->TimeToLive <= ulTime) { /* Shorter lived entry found */
|
||||||
|
ulTime = pMatch->TimeToLive;
|
||||||
|
pCandidate = pMatch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pMatch++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pCandidate != NULL) { /* Found something to free up */
|
||||||
|
pCandidate->Flags = BAC_ADDR_RESERVED;
|
||||||
|
pCandidate->TimeToLive = BAC_ADDR_SHORT_TIME; /* only reserve it for a short while */
|
||||||
|
}
|
||||||
|
|
||||||
|
return(pCandidate);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* File format:
|
/* File format:
|
||||||
DeviceID MAC SNET SADR MAX-APDU
|
DeviceID MAC SNET SADR MAX-APDU
|
||||||
4194303 05 0 0 50
|
4194303 05 0 0 50
|
||||||
@@ -168,6 +233,7 @@ void address_file_init(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
address_add((uint32_t) device_id, max_apdu, &src);
|
address_add((uint32_t) device_id, max_apdu, &src);
|
||||||
|
address_set_device_TTL(device_id, 0, true); /* Mark as static entry */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -177,6 +243,12 @@ void address_file_init(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Clear down the cache and make sure the full complement of entries are *
|
||||||
|
* available. Assume no persistance of memory. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
void address_init(
|
void address_init(
|
||||||
void)
|
void)
|
||||||
{
|
{
|
||||||
@@ -192,6 +264,75 @@ void address_init(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Clear down the cache of any non bound, expired or reserved entries. *
|
||||||
|
* Leave static and unexpired bound entries alone. For use where the cache *
|
||||||
|
* is held in persistant memory which can survive a reset or power cycle. *
|
||||||
|
* This reduces the network traffic on restarts as the cache will have much *
|
||||||
|
* of its entries intact. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void address_init_partial(
|
||||||
|
void)
|
||||||
|
{
|
||||||
|
struct Address_Cache_Entry *pMatch;
|
||||||
|
|
||||||
|
pMatch = Address_Cache;
|
||||||
|
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1] ) {
|
||||||
|
if((pMatch->Flags & BAC_ADDR_IN_USE) != 0) { /* It's in use so let's check further */
|
||||||
|
if(((pMatch->Flags & BAC_ADDR_BIND_REQ) != 0) || (pMatch->TimeToLive == 0))
|
||||||
|
pMatch->Flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((pMatch->Flags & BAC_ADDR_RESERVED) != 0) { /* Reserved entries should be cleared */
|
||||||
|
pMatch->Flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pMatch++;
|
||||||
|
}
|
||||||
|
address_file_init(Address_Cache_Filename);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Set the TTL info for the given device entry. If it is a bound entry we *
|
||||||
|
* set it to static or normal and can change the TTL. If it is unbound we *
|
||||||
|
* can only set the TTL. This is done as a seperate function at the moment *
|
||||||
|
* to avoid breaking the current API. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void address_set_device_TTL(
|
||||||
|
uint32_t device_id,
|
||||||
|
uint32_t TimeOut,
|
||||||
|
bool StaticFlag)
|
||||||
|
{
|
||||||
|
struct Address_Cache_Entry *pMatch;
|
||||||
|
|
||||||
|
pMatch = Address_Cache;
|
||||||
|
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1] ) {
|
||||||
|
if (((pMatch->Flags & BAC_ADDR_IN_USE) != 0) && (pMatch->device_id == device_id)) {
|
||||||
|
if((pMatch->Flags & BAC_ADDR_BIND_REQ) == 0) { /* If bound then we have either static or normaal */
|
||||||
|
if(StaticFlag) {
|
||||||
|
pMatch->Flags |= BAC_ADDR_STATIC;
|
||||||
|
pMatch->TimeToLive = BAC_ADDR_FOREVER;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pMatch->Flags &= ~BAC_ADDR_STATIC;
|
||||||
|
pMatch->TimeToLive = TimeOut;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pMatch->TimeToLive = TimeOut; /* For unbound we can only set the time to live */
|
||||||
|
}
|
||||||
|
break; /* Exit now if found at all - bound or unbound */
|
||||||
|
}
|
||||||
|
pMatch++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool address_get_by_device(
|
bool address_get_by_device(
|
||||||
uint32_t device_id,
|
uint32_t device_id,
|
||||||
unsigned *max_apdu,
|
unsigned *max_apdu,
|
||||||
@@ -218,6 +359,7 @@ bool address_get_by_device(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* find a device id from a given MAC address */
|
/* find a device id from a given MAC address */
|
||||||
|
|
||||||
bool address_get_device_id(
|
bool address_get_device_id(
|
||||||
BACNET_ADDRESS * src,
|
BACNET_ADDRESS * src,
|
||||||
uint32_t * device_id)
|
uint32_t * device_id)
|
||||||
@@ -260,9 +402,21 @@ void address_add(
|
|||||||
pMatch = Address_Cache;
|
pMatch = Address_Cache;
|
||||||
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1] ) {
|
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1] ) {
|
||||||
if (((pMatch->Flags & BAC_ADDR_IN_USE) != 0) && (pMatch->device_id == device_id)) {
|
if (((pMatch->Flags & BAC_ADDR_IN_USE) != 0) && (pMatch->device_id == device_id)) {
|
||||||
pMatch->address = *src;
|
pMatch->address = *src;
|
||||||
pMatch->max_apdu = max_apdu;
|
pMatch->max_apdu = max_apdu;
|
||||||
pMatch->Flags &= ~BAC_ADDR_BIND_REQ; /* Clear bind request flag just in case */
|
|
||||||
|
/* Pick the right time to live */
|
||||||
|
|
||||||
|
if((pMatch->Flags & BAC_ADDR_BIND_REQ) != 0) /* Bind requested so long time */
|
||||||
|
pMatch->TimeToLive = BAC_ADDR_LONG_TIME;
|
||||||
|
else if((pMatch->Flags & BAC_ADDR_STATIC) != 0) /* Static already so make sure it never expires */
|
||||||
|
pMatch->TimeToLive = BAC_ADDR_FOREVER;
|
||||||
|
else if((pMatch->Flags & BAC_ADDR_SHORT_TTL) != 0) /* Opportunistic entry so leave on short fuse */
|
||||||
|
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME;
|
||||||
|
else
|
||||||
|
pMatch->TimeToLive = BAC_ADDR_LONG_TIME; /* Renewing existing entry */
|
||||||
|
|
||||||
|
pMatch->Flags &= ~BAC_ADDR_BIND_REQ; /* Clear bind request flag just in case */
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -278,12 +432,25 @@ void address_add(
|
|||||||
pMatch->device_id = device_id;
|
pMatch->device_id = device_id;
|
||||||
pMatch->max_apdu = max_apdu;
|
pMatch->max_apdu = max_apdu;
|
||||||
pMatch->address = *src;
|
pMatch->address = *src;
|
||||||
|
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME; /* Opportunistic entry so leave on short fuse */
|
||||||
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pMatch++;
|
pMatch++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* See if we can squeeze it in */
|
||||||
|
if (!found) {
|
||||||
|
pMatch = address_remove_oldest();
|
||||||
|
if(pMatch != NULL) {
|
||||||
|
pMatch->Flags = BAC_ADDR_IN_USE;
|
||||||
|
pMatch->device_id = device_id;
|
||||||
|
pMatch->max_apdu = max_apdu;
|
||||||
|
pMatch->address = *src;
|
||||||
|
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME; /* Opportunistic entry so leave on short fuse */
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,28 +472,40 @@ bool address_bind_request(
|
|||||||
found = true;
|
found = true;
|
||||||
*src = pMatch->address;
|
*src = pMatch->address;
|
||||||
*max_apdu = pMatch->max_apdu;
|
*max_apdu = pMatch->max_apdu;
|
||||||
|
if((pMatch->Flags & BAC_ADDR_SHORT_TTL) != 0) { /* Was picked up opportunistacilly */
|
||||||
|
pMatch->Flags &= ~BAC_ADDR_SHORT_TTL; /* Convert to normal entry */
|
||||||
|
pMatch->TimeToLive = BAC_ADDR_LONG_TIME; /* And give it a decent time to live */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return found; /* True if bound, false if bind request outstanding */
|
return(found); /* True if bound, false if bind request outstanding */
|
||||||
}
|
}
|
||||||
pMatch++;
|
pMatch++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found) {
|
/* Not there already so look for a free entry to put it in */
|
||||||
pMatch = Address_Cache;
|
pMatch = Address_Cache;
|
||||||
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1] ) {
|
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1] ) {
|
||||||
if ((pMatch->Flags & BAC_ADDR_IN_USE) == 0) {
|
if ((pMatch->Flags & (BAC_ADDR_IN_USE |BAC_ADDR_RESERVED)) == 0) {
|
||||||
pMatch->Flags = BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ; /* In use and awaiting binding */
|
pMatch->Flags = BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ; /* In use and awaiting binding */
|
||||||
pMatch->device_id = device_id;
|
pMatch->device_id = device_id;
|
||||||
/* now would be a good time to do a Who-Is request */
|
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME; /* No point in leaving bind requests in for long haul */
|
||||||
break;
|
/* now would be a good time to do a Who-Is request */
|
||||||
}
|
return(false);
|
||||||
pMatch++;
|
|
||||||
}
|
}
|
||||||
|
pMatch++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return found;
|
/* No free entries, See if we can squeeze it in by dropping an existing one */
|
||||||
|
pMatch = address_remove_oldest();
|
||||||
|
if(pMatch != NULL) {
|
||||||
|
pMatch->Flags = BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ;
|
||||||
|
pMatch->device_id = device_id;
|
||||||
|
pMatch->TimeToLive = BAC_ADDR_SHORT_TIME; /* No point in leaving bind requests in for long haul */
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void address_add_binding(
|
void address_add_binding(
|
||||||
uint32_t device_id,
|
uint32_t device_id,
|
||||||
unsigned max_apdu,
|
unsigned max_apdu,
|
||||||
@@ -340,7 +519,9 @@ void address_add_binding(
|
|||||||
if (((pMatch->Flags & BAC_ADDR_IN_USE) != 0) && (pMatch->device_id == device_id)) {
|
if (((pMatch->Flags & BAC_ADDR_IN_USE) != 0) && (pMatch->device_id == device_id)) {
|
||||||
pMatch->address = *src;
|
pMatch->address = *src;
|
||||||
pMatch->max_apdu = max_apdu;
|
pMatch->max_apdu = max_apdu;
|
||||||
pMatch->Flags &= ~BAC_ADDR_BIND_REQ; /* Clear bind request flag in case it was set */
|
pMatch->Flags &= ~BAC_ADDR_BIND_REQ; /* Clear bind request flag in case it was set */
|
||||||
|
if((pMatch->Flags & BAC_ADDR_STATIC) == 0) /* Only update TTL if not static */
|
||||||
|
pMatch->TimeToLive = BAC_ADDR_LONG_TIME; /* and set it on a long fuse */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pMatch++;
|
pMatch++;
|
||||||
@@ -359,7 +540,7 @@ bool address_get_by_index(
|
|||||||
|
|
||||||
if (index < MAX_ADDRESS_CACHE) {
|
if (index < MAX_ADDRESS_CACHE) {
|
||||||
pMatch = &Address_Cache[index];
|
pMatch = &Address_Cache[index];
|
||||||
if ((pMatch->Flags & BAC_ADDR_IN_USE) != 0) {
|
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) == BAC_ADDR_IN_USE) {
|
||||||
*src = pMatch->address;
|
*src = pMatch->address;
|
||||||
*device_id = pMatch->device_id;
|
*device_id = pMatch->device_id;
|
||||||
*max_apdu = pMatch->max_apdu;
|
*max_apdu = pMatch->max_apdu;
|
||||||
@@ -387,6 +568,11 @@ unsigned address_count(
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Build a list of the current bindings for the device address binding *
|
||||||
|
* property. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
int address_list_encode(
|
int address_list_encode(
|
||||||
uint8_t * apdu,
|
uint8_t * apdu,
|
||||||
unsigned apdu_len)
|
unsigned apdu_len)
|
||||||
@@ -402,7 +588,7 @@ int address_list_encode(
|
|||||||
|
|
||||||
pMatch = Address_Cache;
|
pMatch = Address_Cache;
|
||||||
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1] ) {
|
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1] ) {
|
||||||
if ((pMatch->Flags & BAC_ADDR_IN_USE) != 0) {
|
if ((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_BIND_REQ)) == BAC_ADDR_IN_USE) {
|
||||||
iLen += encode_application_object_id(&apdu[iLen], OBJECT_DEVICE, pMatch->device_id);
|
iLen += encode_application_object_id(&apdu[iLen], OBJECT_DEVICE, pMatch->device_id);
|
||||||
iLen += encode_application_unsigned(&apdu[iLen], pMatch->address.net);
|
iLen += encode_application_unsigned(&apdu[iLen], pMatch->address.net);
|
||||||
|
|
||||||
@@ -424,6 +610,34 @@ return(iLen);
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Scan the cache and eliminate any expired entries. Should be called *
|
||||||
|
* periodically to ensure the cache is managed correctly. If this function *
|
||||||
|
* is never called at all the whole cache is effectivly rendered static and *
|
||||||
|
* entries never expire unless explicetly deleted. *
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
void address_cache_timer(
|
||||||
|
uint16_t uSeconds) /* Approximate number of seconds since last call to this function */
|
||||||
|
{
|
||||||
|
struct Address_Cache_Entry *pMatch;
|
||||||
|
|
||||||
|
pMatch = Address_Cache;
|
||||||
|
while(pMatch <= &Address_Cache[MAX_ADDRESS_CACHE-1] ) {
|
||||||
|
if (((pMatch->Flags & (BAC_ADDR_IN_USE | BAC_ADDR_RESERVED)) != 0)
|
||||||
|
&& ((pMatch->Flags & BAC_ADDR_STATIC) != 0)) { /* Check all entries holding a slot except statics */
|
||||||
|
if(pMatch->TimeToLive >= uSeconds)
|
||||||
|
pMatch->TimeToLive -= uSeconds;
|
||||||
|
else
|
||||||
|
pMatch->Flags = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pMatch++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef TEST
|
#ifdef TEST
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|||||||
Reference in New Issue
Block a user