Skip to content

Commit ab5fcd7

Browse files
committed
Added live traffic stats counting and output to rnstatus
1 parent 45494f2 commit ab5fcd7

File tree

4 files changed

+106
-10
lines changed

4 files changed

+106
-10
lines changed

RNS/Reticulum.py

+18-2
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,8 @@ def exit_handler():
172172
RNS.Transport.exit_handler()
173173
RNS.Identity.exit_handler()
174174

175-
if RNS.Profiler.ran():
176-
RNS.Profiler.results()
175+
# if RNS.Profiler.ran():
176+
# RNS.Profiler.results()
177177

178178
@staticmethod
179179
def sigint_handler(signal, frame):
@@ -965,6 +965,18 @@ def get_interface_stats(self):
965965
else:
966966
ifstats["bitrate"] = None
967967

968+
if hasattr(interface, "current_rx_speed"):
969+
if interface.current_rx_speed != None:
970+
ifstats["rxs"] = interface.current_rx_speed
971+
else:
972+
ifstats["rxs"] = 0
973+
974+
if hasattr(interface, "current_tx_speed"):
975+
if interface.current_tx_speed != None:
976+
ifstats["txs"] = interface.current_tx_speed
977+
else:
978+
ifstats["txs"] = 0
979+
968980
if hasattr(interface, "peers"):
969981
if interface.peers != None:
970982
ifstats["peers"] = len(interface.peers)
@@ -1002,6 +1014,10 @@ def get_interface_stats(self):
10021014

10031015
stats = {}
10041016
stats["interfaces"] = interfaces
1017+
stats["rxb"] = RNS.Transport.traffic_rxb
1018+
stats["txb"] = RNS.Transport.traffic_txb
1019+
stats["rxs"] = RNS.Transport.speed_rx
1020+
stats["txs"] = RNS.Transport.speed_tx
10051021
if Reticulum.transport_enabled():
10061022
stats["transport_id"] = RNS.Transport.identity.hash
10071023
stats["transport_uptime"] = time.time()-RNS.Transport.start_time

RNS/Transport.py

+43
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ class Transport:
142142
interface_last_jobs = 0.0
143143
interface_jobs_interval = 5.0
144144

145+
traffic_rxb = 0
146+
traffic_txb = 0
147+
speed_rx = 0
148+
speed_tx = 0
149+
traffic_captured = None
150+
145151
identity = None
146152

147153
@staticmethod
@@ -195,6 +201,9 @@ def start(reticulum_instance):
195201
thread = threading.Thread(target=Transport.jobloop, daemon=True)
196202
thread.start()
197203

204+
thread = threading.Thread(target=Transport.count_traffic_loop, daemon=True)
205+
thread.start()
206+
198207
if RNS.Reticulum.transport_enabled():
199208
destination_table_path = RNS.Reticulum.storagepath+"/destination_table"
200209
tunnel_table_path = RNS.Reticulum.storagepath+"/tunnels"
@@ -321,6 +330,40 @@ def prioritize_interfaces():
321330
except Exception as e:
322331
RNS.log(f"Could not prioritize interfaces according to bitrate. The contained exception was: {e}", RNS.LOG_ERROR)
323332

333+
@staticmethod
334+
def count_traffic_loop():
335+
while True:
336+
time.sleep(1)
337+
try:
338+
rxb = 0; txb = 0;
339+
rxs = 0; txs = 0;
340+
for interface in Transport.interfaces:
341+
if not hasattr(interface, "parent_interface") or interface.parent_interface == None:
342+
if hasattr(interface, "transport_traffic_counter"):
343+
now = time.time(); irxb = interface.rxb; itxb = interface.txb
344+
tc = interface.transport_traffic_counter
345+
rx_diff = irxb - tc["rxb"]
346+
tx_diff = itxb - tc["txb"]
347+
ts_diff = now - tc["ts"]
348+
rxb += rx_diff; crxs = (rx_diff*8)/ts_diff
349+
txb += tx_diff; ctxs = (tx_diff*8)/ts_diff
350+
interface.current_rx_speed = crxs; rxs += crxs
351+
interface.current_tx_speed = ctxs; txs += ctxs
352+
tc["rxb"] = irxb;
353+
tc["txb"] = itxb;
354+
tc["ts"] = now;
355+
356+
else:
357+
interface.transport_traffic_counter = {"ts": time.time(), "rxb": interface.rxb, "txb": interface.txb}
358+
359+
Transport.traffic_rxb += rxb
360+
Transport.traffic_txb += txb
361+
Transport.speed_rx = rxs
362+
Transport.speed_tx = txs
363+
364+
except Exception as e:
365+
RNS.log(f"An error occurred while counting interface traffic: {e}", RNS.LOG_ERROR)
366+
324367
@staticmethod
325368
def jobloop():
326369
while (True):

RNS/Utilities/rnstatus.py

+40-3
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def remote_link_established(link):
135135

136136
def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=False, astats=False,
137137
lstats=False, sorting=None, sort_reverse=False, remote=None, management_identity=None,
138-
remote_timeout=RNS.Transport.PATH_REQUEST_TIMEOUT, must_exit=True, rns_instance=None):
138+
remote_timeout=RNS.Transport.PATH_REQUEST_TIMEOUT, must_exit=True, rns_instance=None, traffic_totals=False):
139139

140140
if remote:
141141
require_shared = False
@@ -228,6 +228,10 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
228228
interfaces.sort(key=lambda i: i["rxb"], reverse=not sort_reverse)
229229
if sorting == "tx":
230230
interfaces.sort(key=lambda i: i["txb"], reverse=not sort_reverse)
231+
if sorting == "rxs":
232+
interfaces.sort(key=lambda i: i["rxs"], reverse=not sort_reverse)
233+
if sorting == "txs":
234+
interfaces.sort(key=lambda i: i["txs"], reverse=not sort_reverse)
231235
if sorting == "traffic":
232236
interfaces.sort(key=lambda i: i["rxb"]+i["txb"], reverse=not sort_reverse)
233237
if sorting == "announces" or sorting == "announce":
@@ -364,7 +368,18 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
364368
print(" Announces : {iaf}↑".format(iaf=RNS.prettyfrequency(ifstat["outgoing_announce_frequency"])))
365369
print(" {iaf}↓".format(iaf=RNS.prettyfrequency(ifstat["incoming_announce_frequency"])))
366370

367-
print(" Traffic : {txb}↑\n {rxb}↓".format(rxb=size_str(ifstat["rxb"]), txb=size_str(ifstat["txb"])))
371+
rxb_str = "↓"+RNS.prettysize(ifstat["rxb"])
372+
txb_str = "↑"+RNS.prettysize(ifstat["txb"])
373+
strdiff = len(rxb_str)-len(txb_str)
374+
if strdiff > 0:
375+
txb_str += " "*strdiff
376+
elif strdiff < 0:
377+
rxb_str += " "*-strdiff
378+
379+
rxstat = rxb_str+" "+RNS.prettyspeed(ifstat["rxs"])
380+
txstat = txb_str+" "+RNS.prettyspeed(ifstat["txs"])
381+
382+
print(f" Traffic : {txstat}\n {rxstat}")
368383

369384
lstr = ""
370385
if link_count != None and lstats:
@@ -374,6 +389,19 @@ def program_setup(configdir, dispall=False, verbosity=0, name_filter=None, json=
374389
else:
375390
lstr = f" {link_count} entr{ms} in link table"
376391

392+
if traffic_totals:
393+
rxb_str = "↓"+RNS.prettysize(stats["rxb"])
394+
txb_str = "↑"+RNS.prettysize(stats["txb"])
395+
strdiff = len(rxb_str)-len(txb_str)
396+
if strdiff > 0:
397+
txb_str += " "*strdiff
398+
elif strdiff < 0:
399+
rxb_str += " "*-strdiff
400+
401+
rxstat = rxb_str+" "+RNS.prettyspeed(stats["rxs"])
402+
txstat = txb_str+" "+RNS.prettyspeed(stats["txs"])
403+
print(f"\n Totals : {txstat}\n {rxstat}")
404+
377405
if "transport_id" in stats and stats["transport_id"] != None:
378406
print("\n Transport Instance "+RNS.prettyhexrep(stats["transport_id"])+" running")
379407
if "probe_responder" in stats and stats["probe_responder"] != None:
@@ -426,11 +454,19 @@ def main(must_exit=True, rns_instance=None):
426454
default=False,
427455
)
428456

457+
parser.add_argument(
458+
"-t",
459+
"--totals",
460+
action="store_true",
461+
help="display traffic totals",
462+
default=False,
463+
)
464+
429465
parser.add_argument(
430466
"-s",
431467
"--sort",
432468
action="store",
433-
help="sort interfaces by [rate, traffic, rx, tx, announces, arx, atx, held]",
469+
help="sort interfaces by [rate, traffic, rx, tx, rxs, txs, announces, arx, atx, held]",
434470
default=None,
435471
type=str
436472
)
@@ -504,6 +540,7 @@ def main(must_exit=True, rns_instance=None):
504540
remote_timeout=args.w,
505541
must_exit=must_exit,
506542
rns_instance=rns_instance,
543+
traffic_totals=args.totals,
507544
)
508545

509546
except KeyboardInterrupt:

RNS/__init__.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -481,10 +481,10 @@ def print_tag_results(tag, level):
481481
print(f"{ind} St.dev. : {prettyshorttime(stdev)}")
482482
print("")
483483

484-
print("\nProfiler results:\n")
485-
for tag_name in results:
486-
tag = results[tag_name]
487-
if tag["super"] == None:
488-
print_results_recursive(tag, results)
484+
print("\nProfiler results:\n")
485+
for tag_name in results:
486+
tag = results[tag_name]
487+
if tag["super"] == None:
488+
print_results_recursive(tag, results)
489489

490490
profile = Profiler.get_profiler

0 commit comments

Comments
 (0)