From 378840a6bf827063d7558417301d00a33ea9eeb5 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Fri, 21 Aug 2026 20:59:32 +0200 Subject: [PATCH] Added total announce/pr count stats per interface --- RNS/Interfaces/Interface.py | 26 +++++++++++++++++++------- RNS/Reticulum.py | 4 ++++ RNS/Utilities/rnstatus.py | 24 ++++++++++++++++++++---- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/RNS/Interfaces/Interface.py b/RNS/Interfaces/Interface.py index 829c2d21..075d3e02 100755 --- a/RNS/Interfaces/Interface.py +++ b/RNS/Interfaces/Interface.py @@ -99,8 +99,12 @@ class Interface: self.txb = 0 self.arxb = 0 self.atxb = 0 + self.arxc = 0 + self.atxc = 0 self.prxb = 0 self.ptxb = 0 + self.prxc = 0 + self.ptxc = 0 self.gravity = 0 self.created = time.time() self.detached = False @@ -124,8 +128,10 @@ class Interface: self.ic_burst_active = False self.ic_burst_activated = 0 + self.ic_burst_sustained = 0 self.ic_pr_burst_active = False self.ic_pr_burst_activated = 0 + self.ic_pr_burst_sustained = 0 self.ic_pr_burst_cooldown = 0 self.ic_held_release = 0 self.ic_max_held_announces = RNS.Reticulum.get_instance()._default_ic_max_held_announces() @@ -164,8 +170,10 @@ class Interface: ia_freq = self.incoming_announce_frequency() if self.ic_burst_active: - if ia_freq < freq_threshold and time.time() > self.ic_burst_activated+self.ic_burst_hold: + if ia_freq < freq_threshold and time.time() > self.ic_burst_activated+self.ic_burst_hold and time.time() > self.ic_burst_sustained+self.ic_burst_hold: if len(self.ia_freq_deque) >= self.IC_DEQUE_MIN_SAMPLE: self.ic_burst_active = False + else: + if ia_freq >= freq_threshold: self.ic_burst_sustained = time.time() return True @@ -173,6 +181,7 @@ class Interface: if ia_freq > freq_threshold: self.ic_burst_active = True self.ic_burst_activated = time.time() + self.ic_burst_sustained = time.time() self.ic_held_release = time.time() + self.ic_burst_penalty return True @@ -186,10 +195,12 @@ class Interface: ip_freq = self.incoming_pr_frequency() if self.ic_pr_burst_active: - if ip_freq < freq_threshold and time.time() > self.ic_pr_burst_activated+self.ic_burst_hold: + if ip_freq < freq_threshold and time.time() > self.ic_pr_burst_activated+self.ic_burst_hold and time.time() > self.ic_pr_burst_sustained+self.ic_burst_hold: if self.ic_pr_burst_cooldown <= 0: self.ic_pr_burst_active = False else: self.ic_pr_burst_cooldown -= 1 - else: self.ic_pr_burst_cooldown = 3 + else: + self.ic_pr_burst_cooldown = 3 + if ip_freq >= freq_threshold: self.ic_pr_burst_sustained = time.time() return True @@ -197,6 +208,7 @@ class Interface: if ip_freq > freq_threshold: self.ic_pr_burst_active = True self.ic_pr_burst_activated = time.time() + self.ic_pr_burst_sustained = time.time() self.ic_pr_burst_cooldown = 3 return True @@ -267,25 +279,25 @@ class Interface: RNS.log("The contained exception was: "+str(e), RNS.LOG_ERROR) def received_announce(self, size=0, from_spawned=False): - self.arxb += size + self.arxc += 1; self.arxb += size self.ia_freq_deque.append(time.time()) if hasattr(self, "parent_interface") and self.parent_interface != None: self.parent_interface.received_announce(size=size, from_spawned=True) def sent_announce(self, size=0, from_spawned=False): - self.atxb += size + self.atxc += 1; self.atxb += size self.oa_freq_deque.append(time.time()) if hasattr(self, "parent_interface") and self.parent_interface != None: self.parent_interface.sent_announce(size=size, from_spawned=True) def received_path_request(self, size=0, from_spawned=False): - self.prxb += size + self.prxc += 1; self.prxb += size self.ip_freq_deque.append(time.time()) if hasattr(self, "parent_interface") and self.parent_interface != None: self.parent_interface.received_path_request(size=size, from_spawned=True) def sent_path_request(self, size=0, from_spawned=False): - self.ptxb += size + self.ptxc += 1; self.ptxb += size self.op_freq_deque.append(time.time()) if hasattr(self, "parent_interface") and self.parent_interface != None: self.parent_interface.sent_path_request(size=size, from_spawned=True) diff --git a/RNS/Reticulum.py b/RNS/Reticulum.py index 5cc10664..43903035 100755 --- a/RNS/Reticulum.py +++ b/RNS/Reticulum.py @@ -1526,8 +1526,12 @@ class Reticulum: ifstats["txb"] = interface.txb ifstats["arxb"] = interface.arxb ifstats["atxb"] = interface.atxb + ifstats["arxc"] = interface.arxc + ifstats["atxc"] = interface.atxc ifstats["prxb"] = interface.prxb ifstats["ptxb"] = interface.ptxb + ifstats["prxc"] = interface.prxc + ifstats["ptxc"] = interface.ptxc ifstats["incoming_announce_frequency"] = interface.incoming_announce_frequency() ifstats["outgoing_announce_frequency"] = interface.outgoing_announce_frequency() ifstats["incoming_pr_frequency"] = interface.incoming_pr_frequency() diff --git a/RNS/Utilities/rnstatus.py b/RNS/Utilities/rnstatus.py index b7da9db9..1da09bd2 100644 --- a/RNS/Utilities/rnstatus.py +++ b/RNS/Utilities/rnstatus.py @@ -385,10 +385,18 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json= interfaces.sort(key=lambda i: i["incoming_announce_frequency"], reverse=not sort_reverse) if sorting == "atx": interfaces.sort(key=lambda i: i["outgoing_announce_frequency"], reverse=not sort_reverse) + if sorting == "arxc": + interfaces.sort(key=lambda i: i["arxc"], reverse=not sort_reverse) + if sorting == "atxc": + interfaces.sort(key=lambda i: i["atxc"], reverse=not sort_reverse) if sorting == "prx": interfaces.sort(key=lambda i: i["incoming_pr_frequency"], reverse=not sort_reverse) if sorting == "ptx": interfaces.sort(key=lambda i: i["outgoing_pr_frequency"], reverse=not sort_reverse) + if sorting == "prxc": + interfaces.sort(key=lambda i: i["prxc"], reverse=not sort_reverse) + if sorting == "ptxc": + interfaces.sort(key=lambda i: i["ptxc"], reverse=not sort_reverse) if sorting == "held": interfaces.sort(key=lambda i: i["held_announces"], reverse=not sort_reverse) if sorting == "pvs": @@ -671,13 +679,21 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json= if "packet_filter_hits" in ifstat and ifstat["packet_filter_hits"]: print(f" Flt. Hits : {ifstat['packet_filter_hits']}") - + if psr: - print(f" Path Rqs. : {opf} {rpc_str}") + if ifstat["prxc"] and ifstat["ptxc"]: + print(f" Path Rqs. : {ifstat['prxc']}↓ {ifstat['ptxc']}↑ total") + print(f" {opf} {rpc_str}") + else: + print(f" Path Rqs. : {opf} {rpc_str}") print(f" {ipf} {pburst_str}") if asr: - print(f" Announces : {oaf} {pc_str}") + if ifstat["arxc"] and ifstat["atxc"]: + print(f" Announces : {ifstat['arxc']}↓ {ifstat['atxc']}↑ total") + print(f" {oaf} {pc_str}") + else: + print(f" Announces : {oaf} {pc_str}") print(f" {iaf} {art_str}{burst_str}") rxstat = rxb_str @@ -815,7 +831,7 @@ def main(must_exit=True, rns_instance=None): parser.add_argument("-b", "--blocked-ips", action="store_true", help="show blocked IPs per interface", default=False) parser.add_argument("-t", "--totals", action="store_true", help="display traffic totals", default=False) parser.add_argument("-q", "--queues", action="store_true", help="display queue stats", default=False) - parser.add_argument("-s", "--sort", action="store", help="sort interfaces by [rate, traffic, rx, tx, rxs, txs, announces, arx, atx, held, prx, ptx, pvs, ivs, flt]", default=None, type=str) + parser.add_argument("-s", "--sort", action="store", help="sort interfaces by [rate, traffic, rx, tx, rxs, txs, announces, arx, atx, arxc, atxc, held, prx, ptx, prxc, ptxc, pvs, ivs, flt]", default=None, type=str) parser.add_argument("-r", "--reverse", action="store_true", help="reverse sorting", default=False) parser.add_argument("-j", "--json", action="store_true", help="output in JSON format", default=False) parser.add_argument("-R", action="store", metavar="hash", help="transport identity hash of remote instance to get status from", default=None, type=str)