Throttle NodeInfo direct responses (#11104)
This commit is contained in:
co-authored by
GitHub
parent
077c6e72f4
commit
6bff231d53
@@ -1092,6 +1092,12 @@ bool TrafficManagementModule::shouldRespondToNodeInfo(const meshtastic_MeshPacke
|
|||||||
if (!sendResponse)
|
if (!sendResponse)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
// Checked here, once a reply would actually go out, so declined requests do not consume the budget.
|
||||||
|
if (!directResponseAllowed(getFrom(p), clockMs())) {
|
||||||
|
TM_LOG_DEBUG("NodeInfo direct response throttled for 0x%08x", getFrom(p));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
meshtastic_MeshPacket *reply = router->allocForSending();
|
meshtastic_MeshPacket *reply = router->allocForSending();
|
||||||
if (!reply) {
|
if (!reply) {
|
||||||
TM_LOG_WARN("NodeInfo direct response dropped: no packet buffer");
|
TM_LOG_WARN("NodeInfo direct response dropped: no packet buffer");
|
||||||
@@ -1144,6 +1150,43 @@ bool TrafficManagementModule::shouldRespondToNodeInfo(const meshtastic_MeshPacke
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TrafficManagementModule::directResponseAllowed(NodeNum requestor, uint32_t nowMs)
|
||||||
|
{
|
||||||
|
// Reached from the packet path and from runOnce, so the throttle state needs the same lock as the cache.
|
||||||
|
concurrency::LockGuard guard(&cacheLock);
|
||||||
|
|
||||||
|
if (lastDirectResponseMs != 0 && (nowMs - lastDirectResponseMs) < kDirectResponseGlobalMs)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
DirectResponseThrottleEntry *slot = nullptr;
|
||||||
|
for (size_t i = 0; i < kDirectResponseTrackedRequestors; i++) {
|
||||||
|
if (directResponseSeen[i].requestor == requestor) {
|
||||||
|
if ((nowMs - directResponseSeen[i].lastReplyMs) < kDirectResponsePerRequestorMs)
|
||||||
|
return false;
|
||||||
|
slot = &directResponseSeen[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (slot == nullptr) {
|
||||||
|
// Unseen requester: take a free slot, otherwise reuse the least recently used one.
|
||||||
|
slot = &directResponseSeen[0];
|
||||||
|
for (size_t i = 0; i < kDirectResponseTrackedRequestors; i++) {
|
||||||
|
if (directResponseSeen[i].requestor == 0) {
|
||||||
|
slot = &directResponseSeen[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (directResponseSeen[i].lastReplyMs < slot->lastReplyMs)
|
||||||
|
slot = &directResponseSeen[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slot->requestor = requestor;
|
||||||
|
slot->lastReplyMs = nowMs;
|
||||||
|
lastDirectResponseMs = nowMs;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool TrafficManagementModule::isMinHopsFromRequestor(const meshtastic_MeshPacket *p) const
|
bool TrafficManagementModule::isMinHopsFromRequestor(const meshtastic_MeshPacket *p) const
|
||||||
{
|
{
|
||||||
int8_t hopsAway = getHopsAway(*p, -1);
|
int8_t hopsAway = getHopsAway(*p, -1);
|
||||||
|
|||||||
@@ -293,6 +293,19 @@ class TrafficManagementModule : public MeshModule, private concurrency::OSThread
|
|||||||
|
|
||||||
bool shouldDropPosition(const meshtastic_MeshPacket *p, const meshtastic_Position *pos, uint32_t nowMs);
|
bool shouldDropPosition(const meshtastic_MeshPacket *p, const meshtastic_Position *pos, uint32_t nowMs);
|
||||||
bool shouldRespondToNodeInfo(const meshtastic_MeshPacket *p, bool sendResponse);
|
bool shouldRespondToNodeInfo(const meshtastic_MeshPacket *p, bool sendResponse);
|
||||||
|
|
||||||
|
// Replies go to the requesting packet's unauthenticated `from`, so space them per requester to bound
|
||||||
|
// what any one node can be made to receive, plus a global floor on airtime.
|
||||||
|
static constexpr uint32_t kDirectResponsePerRequestorMs = 60'000UL;
|
||||||
|
static constexpr uint32_t kDirectResponseGlobalMs = 1'000UL;
|
||||||
|
static constexpr size_t kDirectResponseTrackedRequestors = 8;
|
||||||
|
struct DirectResponseThrottleEntry {
|
||||||
|
NodeNum requestor;
|
||||||
|
uint32_t lastReplyMs;
|
||||||
|
};
|
||||||
|
DirectResponseThrottleEntry directResponseSeen[kDirectResponseTrackedRequestors] = {};
|
||||||
|
uint32_t lastDirectResponseMs = 0;
|
||||||
|
bool directResponseAllowed(NodeNum requestor, uint32_t nowMs);
|
||||||
bool isMinHopsFromRequestor(const meshtastic_MeshPacket *p) const;
|
bool isMinHopsFromRequestor(const meshtastic_MeshPacket *p) const;
|
||||||
bool isRateLimited(NodeNum from, uint32_t nowMs);
|
bool isRateLimited(NodeNum from, uint32_t nowMs);
|
||||||
bool shouldDropUnknown(const meshtastic_MeshPacket *p, uint32_t nowMs);
|
bool shouldDropUnknown(const meshtastic_MeshPacket *p, uint32_t nowMs);
|
||||||
|
|||||||
Reference in New Issue
Block a user