2023-09-28 15:30:54 -04:00
|
|
|
from collections import OrderedDict
|
2022-12-15 17:23:54 -05:00
|
|
|
import logging
|
|
|
|
|
2022-12-24 13:53:06 -05:00
|
|
|
from oslo_config import cfg
|
2022-12-15 17:23:54 -05:00
|
|
|
|
2024-04-16 14:34:14 -04:00
|
|
|
from aprsd.packets import collector, core
|
2024-04-05 15:02:26 -04:00
|
|
|
from aprsd.utils import objectstore
|
2022-12-15 17:23:54 -05:00
|
|
|
|
|
|
|
|
2022-12-24 13:53:06 -05:00
|
|
|
CONF = cfg.CONF
|
2022-12-15 17:23:54 -05:00
|
|
|
LOG = logging.getLogger("APRSD")
|
|
|
|
|
|
|
|
|
2024-04-11 21:40:43 -04:00
|
|
|
class PacketList(objectstore.ObjectStoreMixin):
|
2024-04-16 14:34:14 -04:00
|
|
|
"""Class to keep track of the packets we tx/rx."""
|
2022-12-15 17:23:54 -05:00
|
|
|
_instance = None
|
2022-12-18 21:44:23 -05:00
|
|
|
_total_rx: int = 0
|
|
|
|
_total_tx: int = 0
|
2024-04-15 21:39:45 -04:00
|
|
|
maxlen: int = 100
|
2022-12-15 17:23:54 -05:00
|
|
|
|
|
|
|
def __new__(cls, *args, **kwargs):
|
|
|
|
if cls._instance is None:
|
|
|
|
cls._instance = super().__new__(cls)
|
2024-04-15 21:39:45 -04:00
|
|
|
cls._instance.maxlen = CONF.packet_list_maxlen
|
2024-04-16 23:12:58 -04:00
|
|
|
cls._instance._init_data()
|
2022-12-15 17:23:54 -05:00
|
|
|
return cls._instance
|
|
|
|
|
2024-04-16 23:12:58 -04:00
|
|
|
def _init_data(self):
|
|
|
|
self.data = {
|
|
|
|
"types": {},
|
|
|
|
"packets": OrderedDict(),
|
|
|
|
}
|
|
|
|
|
2024-04-16 14:34:14 -04:00
|
|
|
def rx(self, packet: type[core.Packet]):
|
2022-12-17 20:02:49 -05:00
|
|
|
"""Add a packet that was received."""
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
self._total_rx += 1
|
|
|
|
self._add(packet)
|
|
|
|
ptype = packet.__class__.__name__
|
|
|
|
if not ptype in self.data["types"]:
|
|
|
|
self.data["types"][ptype] = {"tx": 0, "rx": 0}
|
|
|
|
self.data["types"][ptype]["rx"] += 1
|
|
|
|
|
2024-04-16 14:34:14 -04:00
|
|
|
def tx(self, packet: type[core.Packet]):
|
2022-12-17 20:02:49 -05:00
|
|
|
"""Add a packet that was received."""
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
self._total_tx += 1
|
|
|
|
self._add(packet)
|
|
|
|
ptype = packet.__class__.__name__
|
|
|
|
if not ptype in self.data["types"]:
|
|
|
|
self.data["types"][ptype] = {"tx": 0, "rx": 0}
|
|
|
|
self.data["types"][ptype]["tx"] += 1
|
|
|
|
|
2023-09-28 12:19:18 -04:00
|
|
|
def add(self, packet):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
self._add(packet)
|
2023-09-28 12:19:18 -04:00
|
|
|
|
|
|
|
def _add(self, packet):
|
2024-04-16 23:12:58 -04:00
|
|
|
if not self.data.get("packets"):
|
|
|
|
self._init_data()
|
2024-04-11 21:40:43 -04:00
|
|
|
if packet.key in self.data["packets"]:
|
|
|
|
self.data["packets"].move_to_end(packet.key)
|
2024-04-15 21:39:45 -04:00
|
|
|
elif len(self.data["packets"]) == self.maxlen:
|
2024-04-11 21:40:43 -04:00
|
|
|
self.data["packets"].popitem(last=False)
|
2024-04-05 15:02:26 -04:00
|
|
|
self.data["packets"][packet.key] = packet
|
2023-09-28 12:19:18 -04:00
|
|
|
|
|
|
|
def find(self, packet):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
return self.data["packets"][packet.key]
|
2023-09-28 12:19:18 -04:00
|
|
|
|
|
|
|
def __len__(self):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
return len(self.data["packets"])
|
2022-12-15 17:23:54 -05:00
|
|
|
|
2022-12-18 21:44:23 -05:00
|
|
|
def total_rx(self):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
return self._total_rx
|
2022-12-15 17:23:54 -05:00
|
|
|
|
2022-12-18 21:44:23 -05:00
|
|
|
def total_tx(self):
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
return self._total_tx
|
2024-03-29 11:51:15 -04:00
|
|
|
|
2024-04-02 14:07:37 -04:00
|
|
|
def stats(self, serializable=False) -> dict:
|
2024-04-14 12:48:09 -04:00
|
|
|
# limit the number of packets to return to 50
|
2024-04-24 13:49:55 -04:00
|
|
|
with self.lock:
|
|
|
|
tmp = OrderedDict(
|
|
|
|
reversed(
|
|
|
|
list(
|
|
|
|
self.data.get("packets", OrderedDict()).items(),
|
|
|
|
),
|
2024-04-16 23:12:58 -04:00
|
|
|
),
|
2024-04-24 13:49:55 -04:00
|
|
|
)
|
|
|
|
pkts = []
|
|
|
|
count = 1
|
|
|
|
for packet in tmp:
|
|
|
|
pkts.append(tmp[packet])
|
|
|
|
count += 1
|
|
|
|
if count > CONF.packet_list_stats_maxlen:
|
|
|
|
break
|
|
|
|
|
|
|
|
stats = {
|
|
|
|
"total_tracked": self._total_rx + self._total_rx,
|
|
|
|
"rx": self._total_rx,
|
|
|
|
"tx": self._total_tx,
|
|
|
|
"types": self.data.get("types", []),
|
|
|
|
"packet_count": len(self.data.get("packets", [])),
|
|
|
|
"maxlen": self.maxlen,
|
|
|
|
"packets": pkts,
|
|
|
|
}
|
|
|
|
return stats
|
2024-04-16 14:34:14 -04:00
|
|
|
|
|
|
|
|
|
|
|
# Now register the PacketList with the collector
|
|
|
|
# every packet we RX and TX goes through the collector
|
|
|
|
# for processing for whatever reason is needed.
|
|
|
|
collector.PacketCollector().register(PacketList)
|