Track network usage in IO analysis
authorAntoine Busque <antoinebusque@gmail.com>
Thu, 19 Mar 2015 18:41:51 +0000 (14:41 -0400)
committerAntoine Busque <antoinebusque@gmail.com>
Thu, 19 Mar 2015 18:41:51 +0000 (14:41 -0400)
linuxautomaton/linuxautomaton/automaton.py
linuxautomaton/linuxautomaton/net.py
linuxautomaton/linuxautomaton/sv.py
lttnganalyses/lttnganalyses/io.py
lttnganalysescli/lttnganalysescli/io.py

index 91709007b811ab856920901f2dcd8d9bb20891f1..992d8f4a1354036a84224811cbabf7390f08e8b3 100644 (file)
@@ -3,6 +3,7 @@
 # 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
@@ -39,7 +40,6 @@ class State:
         self.disks = {}
         self.syscalls = {}
         self.mm = MemoryManagement()
-        self.ifaces = {}
         self.pending_syscalls = []
         self._notification_cbs = {}
 
index b5bd904ab7bb8247c74d9fc05416db754a4bc70d..dcc3ddbbf0381c2bf576fee59c9de6a2dd1fd8c9 100644 (file)
@@ -3,6 +3,7 @@
 # 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
@@ -27,10 +28,7 @@ from linuxautomaton import sp, sv
 
 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,
@@ -40,40 +38,28 @@ class NetStateProvider(sp.StateProvider):
     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'])
index 78b5a83a6f8de14bc9158952d79a7eefda1fbfe9..bb837a76fbde433e7f6ecd617e33a4d5476c5c9d 100644 (file)
@@ -141,18 +141,6 @@ class Disk():
         self.stdev = None
 
 
-class Iface():
-    def __init__(self):
-        self.name = ''
-        self.init_counts()
-
-    def init_counts(self):
-        self.recv_bytes = 0
-        self.recv_packets = 0
-        self.send_bytes = 0
-        self.send_packets = 0
-
-
 class FDType():
     unknown = 0
     disk = 1
index 3eea7f5775d66bcf3fc00b1a736f4a6d453e1ab7..09f3267ede0c06c189bcbd5ac525724dfc16d5f4 100644 (file)
@@ -27,10 +27,53 @@ from .analysis import Analysis
 
 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
index df0c34ff23bf01ff206f845893f81f0298bc0b0b..a22421fb11efc3db6cf7d4660d13f5ab8992b522 100644 (file)
@@ -426,7 +426,7 @@ class IoAnalysis(Command):
     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),
@@ -439,12 +439,12 @@ class IoAnalysis(Command):
     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)
This page took 0.028797 seconds and 5 git commands to generate.