Add PeerDb::handleGossipedRC

pull/1312/head
Stephen Shelton 4 years ago
parent 7109ddc951
commit 595288e046
No known key found for this signature in database
GPG Key ID: EE4BADACCE8B631C

@ -127,6 +127,10 @@ namespace llarp
auto* router = dht.GetRouter();
router->NotifyRouterEvent<tooling::RCGossipReceivedEvent>(router->pubkey(), rc);
router->GossipRCIfNeeded(rc);
auto peerDb = router->peerDb();
if (peerDb)
peerDb->handleGossipedRC(rc);
}
}
return true;

@ -121,6 +121,31 @@ namespace llarp
return itr->second;
}
void
PeerDb::handleGossipedRC(const RouterContact& rc, llarp_time_t now)
{
std::lock_guard gaurd(m_statsLock);
RouterID id(rc.pubkey);
auto& stats = m_peerStats[id];
if (stats.lastRCUpdated < rc.last_updated.count())
{
// we track max expiry as the delta between (time received - last expiration time),
// and this value will often be negative for a healthy router
// TODO: handle case where new RC is also expired? just ignore?
int64_t expiry = (now.count() - (stats.lastRCUpdated + RouterContact::Lifetime.count()));
if (stats.numDistinctRCsReceived == 0)
stats.mostExpiredRCMs = expiry;
else
stats.mostExpiredRCMs = std::max(stats.mostExpiredRCMs, expiry);
stats.numDistinctRCsReceived++;
stats.lastRCUpdated = rc.last_updated.count();
}
}
void
PeerDb::configure(const RouterConfig& routerConfig)
{

@ -81,6 +81,16 @@ namespace llarp
std::optional<PeerStats>
getCurrentPeerStats(const RouterID& routerId) const;
/// Handles a new gossiped RC, updating stats as needed. The database tracks the last
/// advertised update time, so it knows whether this is a new RC or not.
///
/// The given RC is assumed to be valid.
///
/// @param rc is the RouterContact to handle
/// @param now is an optional time representing the current time
void
handleGossipedRC(const RouterContact& rc, llarp_time_t now = time_now_ms());
/// Configures the PeerDb based on RouterConfig
///
/// @param routerConfig

@ -32,6 +32,7 @@ namespace llarp
double peakBandwidthBytesPerSec = 0;
int64_t longestRCReceiveIntervalMs = 0;
int64_t mostExpiredRCMs = 0;
int64_t lastRCUpdated = 0;
PeerStats();
PeerStats(const RouterID& routerId);

@ -11,6 +11,7 @@
#include <functional>
#include <router_contact.hpp>
#include <tooling/router_event.hpp>
#include <peerstats/peer_db.hpp>
#ifdef LOKINET_HIVE
#include "tooling/router_hive.hpp"
@ -151,6 +152,9 @@ namespace llarp
virtual I_RCLookupHandler&
rcLookupHandler() = 0;
virtual std::shared_ptr<PeerDb>
peerDb() = 0;
virtual bool
Sign(Signature& sig, const llarp_buffer_t& buf) const = 0;

@ -582,7 +582,7 @@ namespace llarp
if (conf->router.m_enablePeerStats)
{
LogInfo("Initializing peerdb...");
m_peerDb = std::make_unique<PeerDb>();
m_peerDb = std::make_shared<PeerDb>();
m_peerDb->configure(conf->router);
}

@ -307,6 +307,12 @@ namespace llarp
return _rcLookupHandler;
}
std::shared_ptr<PeerDb>
peerDb() override
{
return m_peerDb;
}
void
GossipRCIfNeeded(const RouterContact rc) override;
@ -496,7 +502,7 @@ namespace llarp
llarp_time_t m_LastStatsReport = 0s;
std::shared_ptr<llarp::KeyManager> m_keyManager;
std::unique_ptr<PeerDb> m_peerDb;
std::shared_ptr<PeerDb> m_peerDb;
uint32_t path_build_count = 0;

@ -3,6 +3,8 @@
#include <numeric>
#include <catch2/catch.hpp>
#include "router_contact.hpp"
#include "util/time.hpp"
TEST_CASE("Test PeerDb PeerStats memory storage", "[PeerDb]")
{
@ -111,3 +113,42 @@ TEST_CASE("Test PeerDb modifyPeerStats", "[PeerDb]")
CHECK(stats.has_value());
CHECK(stats.value().numPathBuilds == 42);
}
TEST_CASE("Test PeerDb handleGossipedRC", "[PeerDb]")
{
const llarp::RouterID id = llarp::test::makeBuf<llarp::RouterID>(0xCA);
auto rcLifetime = llarp::RouterContact::Lifetime;
llarp_time_t now = 0s;
llarp::RouterContact rc;
rc.pubkey = llarp::PubKey(id);
rc.last_updated = 10s;
llarp::PeerDb db;
db.handleGossipedRC(rc, now);
auto stats = db.getCurrentPeerStats(id);
CHECK(stats.has_value());
CHECK(stats.value().mostExpiredRCMs == (0s - rcLifetime).count());
CHECK(stats.value().numDistinctRCsReceived == 1);
CHECK(stats.value().lastRCUpdated == 10000);
now = 9s;
db.handleGossipedRC(rc, now);
stats = db.getCurrentPeerStats(id);
CHECK(stats.has_value());
// these values should remain unchanged, this is not a new RC
CHECK(stats.value().mostExpiredRCMs == (0s - rcLifetime).count());
CHECK(stats.value().numDistinctRCsReceived == 1);
CHECK(stats.value().lastRCUpdated == 10000);
rc.last_updated = 11s;
db.handleGossipedRC(rc, now);
stats = db.getCurrentPeerStats(id);
// new RC received at 9sec, making it (expiration time - 9 sec) expired (a negative number)
CHECK(stats.value().mostExpiredRCMs == (9s - (now + rcLifetime)).count());
CHECK(stats.value().numDistinctRCsReceived == 2);
CHECK(stats.value().lastRCUpdated == 11000);
}

Loading…
Cancel
Save