From 5619bc7121879d36ceafceef8c9f76d27791ca6b Mon Sep 17 00:00:00 2001 From: Sylvain Afchain Date: Thu, 4 Jul 2013 11:44:25 +0200 Subject: [PATCH] Add method to get iptables traffic counters Add methods to iptables_manager to get traffic counters. this is a part of the blueprint bandwidth-router-measurement Change-Id: I6485d1239085e46398126c81e674e399952a4597 --- neutron/agent/linux/iptables_manager.py | 46 +++++++++++ neutron/tests/unit/test_iptables_manager.py | 89 +++++++++++++++++++++ 2 files changed, 135 insertions(+) diff --git a/neutron/agent/linux/iptables_manager.py b/neutron/agent/linux/iptables_manager.py index 50fb79d4a..acb32b821 100644 --- a/neutron/agent/linux/iptables_manager.py +++ b/neutron/agent/linux/iptables_manager.py @@ -567,3 +567,49 @@ class IptablesManager(object): remove_rules.remove(rule) return new_filter + + def _get_traffic_counters_cmd_tables(self, chain, wrap=True): + name = get_chain_name(chain, wrap) + + cmd_tables = [('iptables', key) for key, table in self.ipv4.items() + if name in table._select_chain_set(wrap)] + + cmd_tables += [('ip6tables', key) for key, table in self.ipv6.items() + if name in table._select_chain_set(wrap)] + + return cmd_tables + + def get_traffic_counters(self, chain, wrap=True, zero=False): + """Return the sum of the traffic counters of all rules of a chain.""" + cmd_tables = self._get_traffic_counters_cmd_tables(chain, wrap) + if not cmd_tables: + LOG.warn(_('Attempted to get traffic counters of chain %s which ' + 'does not exist'), chain) + return + + name = get_chain_name(chain, wrap) + acc = {'pkts': 0, 'bytes': 0} + + for cmd, table in cmd_tables: + args = [cmd, '-t', table, '-L', name, '-n', '-v', '-x'] + if zero: + args.append('-Z') + if self.namespace: + args = ['ip', 'netns', 'exec', self.namespace] + args + current_table = (self.execute(args, + root_helper=self.root_helper)) + current_lines = current_table.split('\n') + + for line in current_lines[2:]: + if not line: + break + data = line.split() + if (len(data) < 2 or + not data[0].isdigit() or + not data[1].isdigit()): + break + + acc['pkts'] += int(data[0]) + acc['bytes'] += int(data[1]) + + return acc diff --git a/neutron/tests/unit/test_iptables_manager.py b/neutron/tests/unit/test_iptables_manager.py index 9deaab570..615a72c30 100644 --- a/neutron/tests/unit/test_iptables_manager.py +++ b/neutron/tests/unit/test_iptables_manager.py @@ -464,6 +464,95 @@ class IptablesManagerStateFulTestCase(base.BaseTestCase): self.iptables.ipv4['filter'].remove_rule('nonexistent', '-j DROP') self.mox.VerifyAll() + def test_get_traffic_counters_chain_notexists(self): + iptables_dump = ( + 'Chain OUTPUT (policy ACCEPT 400 packets, 65901 bytes)\n' + ' pkts bytes target prot opt in out source' + ' destination \n' + ' 400 65901 chain1 all -- * * 0.0.0.0/0' + ' 0.0.0.0/0 \n' + ' 400 65901 chain2 all -- * * 0.0.0.0/0' + ' 0.0.0.0/0 \n') + + self.iptables.execute(['iptables', '-t', 'filter', '-L', 'OUTPUT', + '-n', '-v', '-x'], + root_helper=self.root_helper + ).AndReturn(iptables_dump) + self.iptables.execute(['iptables', '-t', 'nat', '-L', 'OUTPUT', '-n', + '-v', '-x'], + root_helper=self.root_helper + ).AndReturn('') + self.iptables.execute(['ip6tables', '-t', 'filter', '-L', 'OUTPUT', + '-n', '-v', '-x'], + root_helper=self.root_helper + ).AndReturn(iptables_dump) + + self.mox.ReplayAll() + acc = self.iptables.get_traffic_counters('chain1') + self.assertIsNone(acc) + + def test_get_traffic_counters(self): + iptables_dump = ( + 'Chain OUTPUT (policy ACCEPT 400 packets, 65901 bytes)\n' + ' pkts bytes target prot opt in out source' + ' destination \n' + ' 400 65901 chain1 all -- * * 0.0.0.0/0' + ' 0.0.0.0/0 \n' + ' 400 65901 chain2 all -- * * 0.0.0.0/0' + ' 0.0.0.0/0 \n') + + self.iptables.execute(['iptables', '-t', 'filter', '-L', 'OUTPUT', + '-n', '-v', '-x'], + root_helper=self.root_helper + ).AndReturn(iptables_dump) + self.iptables.execute(['iptables', '-t', 'nat', '-L', 'OUTPUT', '-n', + '-v', '-x'], + root_helper=self.root_helper + ).AndReturn('') + + self.iptables.execute(['ip6tables', '-t', 'filter', '-L', 'OUTPUT', + '-n', '-v', '-x'], + root_helper=self.root_helper + ).AndReturn(iptables_dump) + + self.mox.ReplayAll() + acc = self.iptables.get_traffic_counters('OUTPUT') + self.assertEquals(acc['pkts'], 1600) + self.assertEquals(acc['bytes'], 263604) + + self.mox.VerifyAll() + + def test_get_traffic_counters_with_zero(self): + iptables_dump = ( + 'Chain OUTPUT (policy ACCEPT 400 packets, 65901 bytes)\n' + ' pkts bytes target prot opt in out source' + ' destination \n' + ' 400 65901 chain1 all -- * * 0.0.0.0/0' + ' 0.0.0.0/0 \n' + ' 400 65901 chain2 all -- * * 0.0.0.0/0' + ' 0.0.0.0/0 \n') + + self.iptables.execute(['iptables', '-t', 'filter', '-L', 'OUTPUT', + '-n', '-v', '-x', '-Z'], + root_helper=self.root_helper + ).AndReturn(iptables_dump) + self.iptables.execute(['iptables', '-t', 'nat', '-L', 'OUTPUT', '-n', + '-v', '-x', '-Z'], + root_helper=self.root_helper + ).AndReturn('') + + self.iptables.execute(['ip6tables', '-t', 'filter', '-L', 'OUTPUT', + '-n', '-v', '-x', '-Z'], + root_helper=self.root_helper + ).AndReturn(iptables_dump) + + self.mox.ReplayAll() + acc = self.iptables.get_traffic_counters('OUTPUT', zero=True) + self.assertEquals(acc['pkts'], 1600) + self.assertEquals(acc['bytes'], 263604) + + self.mox.VerifyAll() + class IptablesManagerStateLessTestCase(base.BaseTestCase): -- 2.45.2