diff --git a/llarp/router/abstractrouter.hpp b/llarp/router/abstractrouter.hpp index f53c2917a..211c18634 100644 --- a/llarp/router/abstractrouter.hpp +++ b/llarp/router/abstractrouter.hpp @@ -81,6 +81,10 @@ namespace llarp tooling::RouterHive* hive = nullptr; #endif + // XXX / TODO: this code shouldn't ever make it into a release binary + virtual void + stopGossipingRC() = 0; + virtual ~AbstractRouter() = default; virtual bool diff --git a/llarp/router/router.cpp b/llarp/router/router.cpp index e92be092e..9a8034a9e 100644 --- a/llarp/router/router.cpp +++ b/llarp/router/router.cpp @@ -125,6 +125,9 @@ namespace llarp void Router::GossipRCIfNeeded(const RouterContact rc) { + if (not m_shouldGossipRC) + return; + /// if we are not a service node forget about gossip if (not IsServiceNode()) return; diff --git a/llarp/router/router.hpp b/llarp/router/router.hpp index 1be5a99c7..db393c073 100644 --- a/llarp/router/router.hpp +++ b/llarp/router/router.hpp @@ -51,6 +51,14 @@ namespace llarp { struct Router final : public AbstractRouter { + // XXX / TODO: this code shouldn't ever make it into a release binary + virtual void + stopGossipingRC() + { + m_shouldGossipRC = false; + } + bool m_shouldGossipRC = true; + llarp_time_t _lastPump = 0s; bool ready; // transient iwp encryption key diff --git a/pybind/llarp/router.cpp b/pybind/llarp/router.cpp index 7531c27c5..8dcedc6a4 100644 --- a/pybind/llarp/router.cpp +++ b/pybind/llarp/router.cpp @@ -10,6 +10,7 @@ namespace llarp py::class_(mod, "AbstractRouter") .def("rc", &AbstractRouter::rc) .def("Stop", &AbstractRouter::Stop) - .def("peerDb", &AbstractRouter::peerDb); + .def("peerDb", &AbstractRouter::peerDb) + .def("stopGossipingRC", &AbstractRouter::stopGossipingRC); } } // namespace llarp diff --git a/test/hive/test_peer_stats.py b/test/hive/test_peer_stats.py index fd47b656f..4d0530ed0 100644 --- a/test/hive/test_peer_stats.py +++ b/test/hive/test_peer_stats.py @@ -6,50 +6,72 @@ def test_peer_stats(HiveForPeerStats): numRelays = 12 hive = HiveForPeerStats(n_relays=numRelays, n_clients=0, netid="hive") + someRouterId = None - start_time = time() - cur_time = start_time - test_duration = 30 #seconds + def collectStatsForAWhile(duration): + print("collecting router hive stats for {} seconds...", duration) - # we track the number of attempted sessions and inbound/outbound established sessions - numInbound = 0 - numOutbound = 0 - numAttempts = 0 + start_time = time() + cur_time = start_time - # we pick an arbitrary router out of our routers - someRouterId = None + # we track the number of attempted sessions and inbound/outbound established sessions + numInbound = 0 + numOutbound = 0 + numAttempts = 0 + + nonlocal someRouterId + + while cur_time < start_time + duration: + hive.CollectAllEvents() + + for event in hive.events: + event_name = event.__class__.__name__ + + if event_name == "LinkSessionEstablishedEvent": + if event.inbound: + numInbound += 1 + else: + numOutbound += 1 + + if event_name == "ConnectionAttemptEvent": + numAttempts += 1 - while cur_time < start_time + test_duration: + # we pick an arbitrary router out of our routers + if someRouterId is None: + someRouterId = event.remoteId; - hive.CollectAllEvents() + hive.events = [] + cur_time = time() - for event in hive.events: - event_name = event.__class__.__name__ + # these should be strictly equal, although there is variation because of + # the time we sample + print("test duration exceeded") + print("in: {} out: {} attempts: {}", numInbound, numOutbound, numAttempts); + totalReceived = tally_rc_received_for_peer(hive.hive, someRouterId) - if event_name == "LinkSessionEstablishedEvent": - if event.inbound: - numInbound += 1 - else: - numOutbound += 1 + # every router should have received this relay's RC exactly once + print("total times RC received: {} numRelays: {}", totalReceived, numRelays) - if event_name == "ConnectionAttemptEvent": - numAttempts += 1 + return { + "numInbound": numInbound, + "numOutbound": numOutbound, + "numAttempts": numAttempts, + "totalTargetRCsReceived": totalReceived, + }; - if someRouterId is None: - someRouterId = event.remoteId; + results1 = collectStatsForAWhile(30); + assert(results1["totalTargetRCsReceived"] == numRelays) - hive.events = [] - cur_time = time() + # stop our router from gossiping + router = hive.hive.GetRelay(someRouterId, True) + router.stopGossipingRC(); - # these should be strictly equal, although there is variation because of - # the time we sample - print("test duration exceeded") - print("in: {} out: {} attempts: {}", numInbound, numOutbound, numAttempts); - totalReceived = tally_rc_received_for_peer(hive.hive, someRouterId) + ignore = collectStatsForAWhile(30); - # every router should have received this relay's RC exactly once - print("total times RC received: {} numRelays: {}", totalReceived, numRelays) - assert(totalReceived == numRelays) + # ensure that no one hears a fresh RC from this router again + print("Starting second (longer) stats collection...") + results2 = collectStatsForAWhile(3600); + assert(results2["totalTargetRCsReceived"] == numRelays) # should not have increased def tally_rc_received_for_peer(hive, routerId):