88
99#define MAX_PACKET_HASHES 128
1010#define MAX_PACKET_ACKS 64
11- #define HASH_TTL_MS 60000 // 60 seconds - entries older than this are considered expired
1211
1312class SimpleMeshTables : public mesh ::MeshTables {
1413 uint8_t _hashes[MAX_PACKET_HASHES*MAX_HASH_SIZE];
15- uint16_t _last_seen[MAX_PACKET_HASHES]; // timestamp for LRU + TTL, wraps every 65s
14+ uint32_t _last_seen[MAX_PACKET_HASHES]; // timestamp for LRU eviction
1615 uint32_t _acks[MAX_PACKET_ACKS];
1716 int _next_ack_idx;
1817 uint32_t _direct_dups, _flood_dups;
@@ -34,7 +33,7 @@ class SimpleMeshTables : public mesh::MeshTables {
3433 f.read ((uint8_t *) &_acks[0 ], sizeof (_acks));
3534 f.read ((uint8_t *) &_next_ack_idx, sizeof (_next_ack_idx));
3635 // Treat restored hashes as just seen - give them fresh timestamps
37- uint16_t now = millis ();
36+ uint32_t now = millis ();
3837 const uint8_t * sp = _hashes;
3938 for (int i = 0 ; i < MAX_PACKET_HASHES; i++, sp += MAX_HASH_SIZE) {
4039 // Check if slot has data (not all zeros)
@@ -74,49 +73,37 @@ class SimpleMeshTables : public mesh::MeshTables {
7473 return false ;
7574 }
7675
77- uint16_t now = millis ();
76+ uint32_t now = millis ();
7877 uint8_t hash[MAX_HASH_SIZE];
7978 packet->calculatePacketHash (hash);
8079
8180 int oldest_idx = 0 ;
82- uint16_t oldest_age = 0 ;
83- int expired_idx = -1 ;
81+ uint32_t oldest_age = 0 ;
8482
8583 const uint8_t * sp = _hashes;
8684 for (int i = 0 ; i < MAX_PACKET_HASHES; i++, sp += MAX_HASH_SIZE) {
87- uint16_t age = (uint16_t )(now - _last_seen[i]);
88-
89- if (memcmp (hash, sp, MAX_HASH_SIZE) == 0 ) {
90- // Check if expired (last_seen == 0 means never set)
91- if (_last_seen[i] != 0 && age <= HASH_TTL_MS) {
92- // Valid match - refresh timestamp (LRU touch) and return true
93- _last_seen[i] = now;
94- if (packet->isRouteDirect ()) {
95- _direct_dups++; // keep some stats
96- } else {
97- _flood_dups++;
98- }
99- return true ;
85+ uint32_t age = now - _last_seen[i];
86+
87+ if (memcmp (hash, sp, MAX_HASH_SIZE) == 0 && _last_seen[i] != 0 ) {
88+ // Match found - refresh timestamp (LRU touch) and return true
89+ _last_seen[i] = now;
90+ if (packet->isRouteDirect ()) {
91+ _direct_dups++; // keep some stats
92+ } else {
93+ _flood_dups++;
10094 }
101- // Expired match - treat as not seen, reuse this slot
102- expired_idx = i;
103- break ;
95+ return true ;
10496 }
10597
10698 // Track oldest entry for LRU eviction
10799 if (age > oldest_age) {
108100 oldest_age = age;
109101 oldest_idx = i;
110102 }
111-
112- // Track first expired slot (including never-used slots where last_seen == 0)
113- if (expired_idx < 0 && (_last_seen[i] == 0 || age > HASH_TTL_MS)) {
114- expired_idx = i;
115- }
116103 }
117104
118- // Not found - insert into expired slot or evict oldest (LRU)
119- int insert_idx = (expired_idx >= 0 ) ? expired_idx : oldest_idx;
105+ // Not found - evict oldest (LRU)
106+ int insert_idx = oldest_idx;
120107 memcpy (&_hashes[insert_idx*MAX_HASH_SIZE], hash, MAX_HASH_SIZE);
121108 _last_seen[insert_idx] = now;
122109 return false ;
0 commit comments