@@ -315,9 +315,9 @@ TrafficManagementModule::UnifiedCacheEntry *TrafficManagementModule::findOrCreat
315315 const uint8_t unknownAgePosScale =
316316 static_cast <uint8_t >(static_cast <uint8_t >((currentUnknownTick () - e.getUnknownTime ()) & 0x0F ) / 6 );
317317 uint8_t recencyAge = posAge;
318- if (e.rate_count != 0 && rateAgePosScale > recencyAge)
318+ if (e.getRateCount () != 0 && rateAgePosScale > recencyAge)
319319 recencyAge = rateAgePosScale;
320- if (e.unknown_count != 0 && unknownAgePosScale > recencyAge)
320+ if (e.getUnknownCount () != 0 && unknownAgePosScale > recencyAge)
321321 recencyAge = unknownAgePosScale;
322322 const uint8_t recency = static_cast <uint8_t >(UINT8_MAX - recencyAge);
323323 if (!victim || (hasHop == victimHasHop ? recency < victimRecency : !hasHop)) {
@@ -876,20 +876,20 @@ int32_t TrafficManagementModule::runOnce()
876876 }
877877 }
878878
879- // Check and clear expired rate limit data (gated on feature; presence: rate_count != 0)
880- if (cfg.rate_limit_enabled && cache[i].rate_count != 0 ) {
879+ // Check and clear expired rate limit data (gated on feature; presence: getRateCount() != 0)
880+ if (cfg.rate_limit_enabled && cache[i].getRateCount () != 0 ) {
881881 if ((static_cast <uint8_t >(nowRateTick - cache[i].getRateTime ()) & 0x0F ) >= rateTtlTicks) {
882- cache[i].rate_count = 0 ;
882+ cache[i].setRateCount ( 0 ) ;
883883 cache[i].setRateTime (0 );
884884 } else {
885885 anyValid = true ;
886886 }
887887 }
888888
889- // Check and clear expired unknown tracking data (gated on feature; presence: unknown_count != 0)
890- if (cfg.drop_unknown_enabled && cache[i].unknown_count != 0 ) {
889+ // Check and clear expired unknown tracking data (gated on feature; presence: getUnknownCount() != 0)
890+ if (cfg.drop_unknown_enabled && cache[i].getUnknownCount () != 0 ) {
891891 if ((static_cast <uint8_t >(nowUnknownTick - cache[i].getUnknownTime ()) & 0x0F ) >= unknownTtlTicks) {
892- cache[i].unknown_count = 0 ;
892+ cache[i].setUnknownCount ( 0 ) ;
893893 cache[i].setUnknownTime (0 );
894894 } else {
895895 anyValid = true ;
@@ -1149,30 +1149,40 @@ bool TrafficManagementModule::isRateLimited(NodeNum from, uint32_t nowMs)
11491149 if (!entry)
11501150 return false ;
11511151
1152+ // Refresh cached role from hot store when we have a confirmed user record; leave
1153+ // stale value otherwise so evicted-from-both-stores nodes retain their last role.
1154+ if (nodeDB) {
1155+ const meshtastic_NodeInfoLite *info = nodeDB->getMeshNode (from);
1156+ if (nodeInfoLiteHasUser (info))
1157+ entry->setCachedRole (static_cast <uint8_t >(std::min (15 , (int )info->role )));
1158+ }
1159+
11521160 // Window ticks: clamp to [1,15] so zero windowMs (config error) opens a new window.
11531161 const uint8_t windowTicks = static_cast <uint8_t >(std::min (static_cast <uint32_t >(15 ), windowMs / kRateTimeTickMs ));
11541162 const uint8_t nowRateTick = currentRateTick ();
11551163 const bool windowExpired =
1156- isNew || entry->rate_count == 0 ||
1164+ isNew || entry->getRateCount () == 0 ||
11571165 ((static_cast <uint8_t >(nowRateTick - entry->getRateTime ()) & 0x0F ) >= std::max (static_cast <uint8_t >(1 ), windowTicks));
11581166 if (windowExpired) {
11591167 entry->setRateTime (nowRateTick);
1160- entry->rate_count = 1 ;
1168+ entry->setRateCount ( 1 ) ;
11611169 return false ;
11621170 }
11631171
1164- // Increment counter (saturates at 255)
1165- saturatingIncrement (entry->rate_count );
1172+ // Increment counter, saturating at 63 (6-bit field max).
1173+ const uint8_t cur = entry->getRateCount ();
1174+ if (cur < 0x3F )
1175+ entry->setRateCount (static_cast <uint8_t >(cur + 1 ));
11661176
1167- // Check against threshold (uint8_t max is 255, but config is uint32_t)
1177+ // Threshold capped at 60 so a saturated reading (63) always exceeds it.
11681178 uint32_t threshold = moduleConfig.traffic_management .rate_limit_max_packets ;
1169- if (threshold > 255 )
1170- threshold = 255 ;
1179+ if (threshold > 60 )
1180+ threshold = 60 ;
11711181
1172- bool limited = entry->rate_count > threshold ;
1173- if ( limited || entry-> rate_count == threshold) {
1174- TM_LOG_DEBUG ( " Rate limit 0x%08x: count=%u threshold=%u -> %s " , from, entry-> rate_count , threshold,
1175- limited ? " DROP" : " at-limit" );
1182+ const uint8_t count = entry->getRateCount () ;
1183+ bool limited = count > threshold;
1184+ if (limited || count == threshold) {
1185+ TM_LOG_DEBUG ( " Rate limit 0x%08x: count=%u threshold=%u -> %s " , from, count, threshold, limited ? " DROP" : " at-limit" );
11761186 }
11771187 return limited;
11781188#endif
@@ -1197,28 +1207,31 @@ bool TrafficManagementModule::shouldDropUnknown(const meshtastic_MeshPacket *p,
11971207 if (!entry)
11981208 return false ;
11991209
1200- // Check if window has expired (presence: unknown_count != 0)
1210+ // Check if window has expired (presence: getUnknownCount() != 0)
12011211 const uint8_t nowUnknownTick = currentUnknownTick ();
1202- const bool windowExpired = isNew || entry->unknown_count == 0 ||
1212+ const bool windowExpired = isNew || entry->getUnknownCount () == 0 ||
12031213 ((static_cast <uint8_t >(nowUnknownTick - entry->getUnknownTime ()) & 0x0F ) >= kUnknownWindowTicks );
12041214 if (windowExpired) {
12051215 entry->setUnknownTime (nowUnknownTick);
1206- entry->unknown_count = 0 ;
1216+ entry->setUnknownCount ( 0 ) ;
12071217 }
12081218
1209- // Increment counter (saturates at 255). Same saturation handling as
1210- // isRateLimited: without it, a clamped threshold of 255 can never fire.
1211- const bool alreadySaturated = (entry->unknown_count == UINT8_MAX );
1212- saturatingIncrement (entry->unknown_count );
1219+ // Increment counter, saturating at 63 (6-bit field max). With threshold
1220+ // capped at 60, a saturated reading always exceeds the limit — no special
1221+ // already-saturated edge case needed.
1222+ const uint8_t cur = entry->getUnknownCount ();
1223+ if (cur < 0x3F )
1224+ entry->setUnknownCount (static_cast <uint8_t >(cur + 1 ));
12131225
1214- // Check against threshold
1226+ // Threshold capped at 60 so a saturated reading (63) always exceeds it.
12151227 uint32_t threshold = moduleConfig.traffic_management .unknown_packet_threshold ;
1216- if (threshold > 255 )
1217- threshold = 255 ;
1228+ if (threshold > 60 )
1229+ threshold = 60 ;
12181230
1219- bool drop = entry->unknown_count > threshold || (alreadySaturated && threshold == 255 );
1220- if (drop || entry->unknown_count == threshold) {
1221- TM_LOG_DEBUG (" Unknown packets 0x%08x: count=%u threshold=%u -> %s" , p->from , entry->unknown_count , threshold,
1231+ const uint8_t count = entry->getUnknownCount ();
1232+ bool drop = count > threshold;
1233+ if (drop || count == threshold) {
1234+ TM_LOG_DEBUG (" Unknown packets 0x%08x: count=%u threshold=%u -> %s" , p->from , count, threshold,
12221235 drop ? " DROP" : " at-limit" );
12231236 }
12241237 return drop;
0 commit comments