# The MIT License (MIT)
#
# Copyright (C) 2015 - Julien Desfossez <jdesfossez@efficios.com>
+# 2015 - Antoine Busque <abusque@efficios.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
class NetStateProvider(sp.StateProvider):
def __init__(self, state):
- self.state = state
- self.ifaces = state.ifaces
- self.cpus = state.cpus
- self.tids = state.tids
+ self._state = state
cbs = {
'net_dev_xmit': self._process_net_dev_xmit,
'netif_receive_skb': self._process_netif_receive_skb,
def process_event(self, ev):
self._process_event_cb(ev)
- def get_dev(self, dev):
- if dev not in self.ifaces:
- d = sv.Iface()
- d.name = dev
- self.ifaces[dev] = d
- else:
- d = self.ifaces[dev]
- return d
-
def _process_net_dev_xmit(self, event):
- dev = event['name']
- sent_len = event['len']
- cpu_id = event['cpu_id']
+ self._state.send_notification_cb('net_dev_xmit',
+ iface_name=event['name'],
+ sent_bytes=event['len'])
- d = self.get_dev(dev)
- d.send_packets += 1
- d.send_bytes += sent_len
-
- if cpu_id not in self.cpus.keys():
+ cpu_id = event['cpu_id']
+ if cpu_id not in self._state.cpus:
return
- c = self.cpus[cpu_id]
- if c.current_tid is None:
+
+ cpu = self._state.cpus[cpu_id]
+ if cpu.current_tid is None:
return
- t = self.tids[c.current_tid]
- if not t.current_syscall:
+
+ current_syscall = self._state.tids[cpu.current_tid].current_syscall
+ if not current_syscall:
return
- if t.current_syscall['name'] in sv.SyscallConsts.WRITE_SYSCALLS:
- if t.current_syscall['fd'].fdtype == sv.FDType.unknown:
- t.current_syscall['fd'].fdtype = sv.FDType.maybe_net
- def _process_netif_receive_skb(self, event):
- dev = event['name']
- recv_len = event['len']
+ if current_syscall['name'] in sv.SyscallConsts.WRITE_SYSCALLS and \
+ current_syscall['fd'].fdtype == sv.FDType.unknown:
+ current_syscall['fd'].fdtype = sv.FDType.maybe_net
- d = self.get_dev(dev)
- d.recv_packets += 1
- d.recv_bytes += recv_len
+ def _process_netif_receive_skb(self, event):
+ self._state.send_notification_cb('netif_receive_skb',
+ iface_name=event['name'],
+ recv_bytes=event['len'])
class IoAnalysis(Analysis):
def __init__(self, state):
+ notification_cbs = {
+ 'net_dev_xmit': self._process_net_dev_xmit,
+ 'netif_receive_skb': self._process_netif_receive_skb
+ }
+
self._state = state
+ self._state.register_notification_cbs(notification_cbs)
+ self.ifaces = {}
def process_event(self, ev):
pass
def reset(self):
- pass
+ for iface in self.ifaces:
+ iface.reset()
+
+ def _process_net_dev_xmit(self, **kwargs):
+ name = kwargs['iface_name']
+ sent_bytes = kwargs['sent_bytes']
+
+ if name not in self.ifaces:
+ self.ifaces[name] = IfaceStats(name)
+
+ self.ifaces[name].sent_packets += 1
+ self.ifaces[name].sent_bytes += sent_bytes
+
+ def _process_netif_receive_skb(self, **kwargs):
+ name = kwargs['iface_name']
+ recv_bytes = kwargs['recv_bytes']
+
+ if name not in self.ifaces:
+ self.ifaces[name] = IfaceStats(name)
+
+ self.ifaces[name].recv_packets += 1
+ self.ifaces[name].recv_bytes += recv_bytes
+
+
+class IfaceStats():
+ def __init__(self, name):
+ self.name = name
+ self.recv_bytes = 0
+ self.recv_packets = 0
+ self.sent_bytes = 0
+ self.sent_packets = 0
+
+ def reset(self):
+ self.recv_bytes = 0
+ self.recv_packets = 0
+ self.sent_bytes = 0
+ self.sent_packets = 0
def iotop_output_net_recv_bytes(self):
graph = Pyasciigraph()
values = []
- for iface in sorted(self.state.ifaces.values(),
+ for iface in sorted(self._analysis.ifaces.values(),
key=operator.attrgetter('recv_bytes'),
reverse=True):
values.append(('%s %s' % (common.convert_size(iface.recv_bytes),
def iotop_output_net_sent_bytes(self):
graph = Pyasciigraph()
values = []
- for iface in sorted(self.state.ifaces.values(),
- key=operator.attrgetter('send_bytes'),
+ for iface in sorted(self._analysis.ifaces.values(),
+ key=operator.attrgetter('sent_bytes'),
reverse=True):
- values.append(('%s %s' % (common.convert_size(iface.send_bytes),
+ values.append(('%s %s' % (common.convert_size(iface.sent_bytes),
iface.name),
- iface.send_bytes))
+ iface.sent_bytes))
for line in graph.graph('Network sent_bytes', values,
with_value=False):
print(line)