stats: python vpp_stats rewrite to access stat segment directly

This module implement Python access to the VPP statistics segment. It
accesses the data structures directly in shared memory.
VPP uses optimistic locking, so data structures may change underneath
us while we are reading. Data is copied out and it's important to
spend as little time as possible "holding the lock".

Counters are stored in VPP as a two dimensional array.
Index by thread and index (typically sw_if_index).
Simple counters count only packets, Combined counters count packets
and octets.

Counters can be accessed in either dimension.
stat['/if/rx'] - returns 2D lists
stat['/if/rx'][0] - returns counters for all interfaces for thread 0
stat['/if/rx'][0][1] - returns counter for interface 1 on thread 0
stat['/if/rx'][0][1]['packets'] - returns the packet counter
                                  for interface 1 on thread 0
stat['/if/rx'][:, 1] - returns the counters for interface 1 on all threads
stat['/if/rx'][:, 1].packets() - returns the packet counters for
                                 interface 1 on all threads
stat['/if/rx'][:, 1].sum_packets() - returns the sum of packet counters for
                                     interface 1 on all threads
stat['/if/rx-miss'][:, 1].sum() - returns the sum of packet counters for
                                  interface 1 on all threads for simple counters

Type: refactor
Signed-off-by: Ole Troan <ot@cisco.com>
Change-Id: I1fe7f7c7d11378d06be8276db5e1900ecdb8f515
Signed-off-by: Ole Troan <ot@cisco.com>
This commit is contained in:
Ole Troan
2021-03-18 11:12:01 +01:00
committed by Neale Ranns
parent fd243741e0
commit e66443c9b4
11 changed files with 555 additions and 407 deletions

View File

@ -41,7 +41,7 @@
#include <urpf/urpf_dp.h>
static char *ip4_urpf_error_strings[] = {
#define _(a,b) "ip4-" # b,
#define _(a, b) b,
foreach_urpf_error
#undef _
};

View File

@ -41,7 +41,7 @@
#include <urpf/urpf_dp.h>
static char *ip6_urpf_error_strings[] = {
#define _(a,b) "ip6-" # b,
#define _(a, b) b,
foreach_urpf_error
#undef _
};

View File

@ -90,7 +90,8 @@ class TestURPF(VppTestCase):
# packets from address to which there is no route are dropped
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
self.assert_error_counter_equal("ip4-rx-urpf-loose", N_PKTS)
self.assert_error_counter_equal("/err/ip4-rx-urpf-loose/uRPF Drop",
N_PKTS)
#
# crank it up to strict mode
@ -106,7 +107,8 @@ class TestURPF(VppTestCase):
self.send_and_assert_no_replies(self.pg0, p_spoof_strict)
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
self.assert_error_counter_equal("ip4-rx-urpf-strict", 2 * N_PKTS)
self.assert_error_counter_equal("/err/ip4-rx-urpf-strict/uRPF Drop",
2 * N_PKTS)
#
# disable uRPF, all traffic should pass
@ -136,7 +138,8 @@ class TestURPF(VppTestCase):
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
self.assert_error_counter_equal("ip4-tx-urpf-loose", N_PKTS)
self.assert_error_counter_equal("/err/ip4-tx-urpf-loose/uRPF Drop",
N_PKTS)
self.vapi.urpf_update(is_input=False,
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_STRICT,
@ -149,7 +152,8 @@ class TestURPF(VppTestCase):
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
self.assert_error_counter_equal("ip4-tx-urpf-strict", N_PKTS)
self.assert_error_counter_equal("/err/ip4-tx-urpf-strict/uRPF Drop",
N_PKTS)
# change the strict packet so that it would forward through pg1
p_spoof_strict = (Ether(dst=self.pg0.local_mac,
@ -160,7 +164,8 @@ class TestURPF(VppTestCase):
Raw(b'\xa5' * 100)) * N_PKTS
self.send_and_assert_no_replies(self.pg0, p_spoof_strict)
self.assert_error_counter_equal("ip4-tx-urpf-strict", 2 * N_PKTS)
self.assert_error_counter_equal("/err/ip4-tx-urpf-strict/uRPF Drop",
2 * N_PKTS)
# cleanup
self.vapi.urpf_update(is_input=False,
@ -212,7 +217,8 @@ class TestURPF(VppTestCase):
# packets from address to which there is no route are dropped
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
self.assert_error_counter_equal("ip6-rx-urpf-loose", N_PKTS)
self.assert_error_counter_equal("/err/ip6-rx-urpf-loose/uRPF Drop",
N_PKTS)
#
# crank it up to strict mode
@ -228,7 +234,8 @@ class TestURPF(VppTestCase):
self.send_and_assert_no_replies(self.pg0, p_spoof_strict)
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
self.assert_error_counter_equal("ip6-rx-urpf-strict", 2 * N_PKTS)
self.assert_error_counter_equal("/err/ip6-rx-urpf-strict/uRPF Drop",
2 * N_PKTS)
#
# disable uRPF, all traffic should pass
@ -258,7 +265,8 @@ class TestURPF(VppTestCase):
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
self.assert_error_counter_equal("ip6-tx-urpf-loose", N_PKTS)
self.assert_error_counter_equal("/err/ip6-tx-urpf-loose/uRPF Drop",
N_PKTS)
self.vapi.urpf_update(is_input=False,
mode=e.vl_api_urpf_mode_t.URPF_API_MODE_STRICT,
@ -271,7 +279,8 @@ class TestURPF(VppTestCase):
self.send_and_expect(self.pg0, p_spoof_strict, self.pg1)
self.send_and_assert_no_replies(self.pg0, p_spoof_loose)
self.assert_error_counter_equal("ip6-tx-urpf-strict", N_PKTS)
self.assert_error_counter_equal("/err/ip6-tx-urpf-strict/uRPF Drop",
N_PKTS)
# change the strict packet so that it would forward through pg1
p_spoof_strict = (Ether(dst=self.pg0.local_mac,
@ -282,7 +291,8 @@ class TestURPF(VppTestCase):
Raw(b'\xa5' * 100)) * N_PKTS
self.send_and_assert_no_replies(self.pg0, p_spoof_strict)
self.assert_error_counter_equal("ip6-tx-urpf-strict", 2 * N_PKTS)
self.assert_error_counter_equal("/err/ip6-tx-urpf-strict/uRPF Drop",
2 * N_PKTS)
# cleanup
self.vapi.urpf_update(is_input=False,

View File

@ -39,10 +39,9 @@ typedef enum
} ah_encrypt_next_t;
#define foreach_ah_encrypt_error \
_(RX_PKTS, "AH pkts received") \
_(CRYPTO_ENGINE_ERROR, "crypto engine error (packet dropped)") \
_(SEQ_CYCLED, "sequence number cycled")
_ (RX_PKTS, "AH pkts received") \
_ (CRYPTO_ENGINE_ERROR, "crypto engine error (packet dropped)") \
_ (SEQ_CYCLED, "sequence number cycled (packet dropped)")
typedef enum
{

758
src/vpp-api/python/vpp_papi/vpp_stats.py Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1177,7 +1177,7 @@ class VppTestCase(unittest.TestCase):
"packet counter `%s'" % counter)
def assert_error_counter_equal(self, counter, expected_value):
counter_value = self.statistics.get_err_counter(counter)
counter_value = self.statistics[counter].sum()
self.assert_equal(counter_value, expected_value,
"error counter `%s'" % counter)

View File

@ -328,7 +328,8 @@ class IpsecTra4(object):
p = self.params[socket.AF_INET]
esn_en = p.vpp_tra_sa.esn_en
seq_cycle_node_name = ('/err/%s/sequence number cycled' %
seq_cycle_node_name = \
('/err/%s/sequence number cycled (packet dropped)' %
self.tra4_encrypt_node_name)
replay_count = self.get_replay_counts(p)
hash_failed_count = self.get_hash_failed_counts(p)

View File

@ -654,10 +654,8 @@ class TestIpsec4MultiTunIfEsp(TemplateIpsec4TunProtect,
"""Multiple IPSEC tunnel interfaces """
for p in self.multi_params:
self.verify_tun_44(p, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 127)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 127)
self.assertEqual(p.tun_if.get_rx_stats(), 127)
self.assertEqual(p.tun_if.get_tx_stats(), 127)
def test_tun_rr_44(self):
""" Round-robin packets acrros multiple interface """
@ -929,10 +927,8 @@ class TestIpsec6MultiTunIfEsp(TemplateIpsec6TunProtect,
"""Multiple IPSEC tunnel interfaces """
for p in self.multi_params:
self.verify_tun_66(p, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 127)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 127)
self.assertEqual(p.tun_if.get_rx_stats(), 127)
self.assertEqual(p.tun_if.get_tx_stats(), 127)
class TestIpsecGreTebIfEsp(TemplateIpsec,
@ -1997,17 +1993,13 @@ class TestIpsec4TunProtect(TemplateIpsec,
self.config_protect(p)
self.verify_tun_44(p, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 127)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 127)
self.assertEqual(p.tun_if.get_rx_stats(), 127)
self.assertEqual(p.tun_if.get_tx_stats(), 127)
self.vapi.cli("clear ipsec sa")
self.verify_tun_64(p, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 254)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 254)
self.assertEqual(p.tun_if.get_rx_stats(), 254)
self.assertEqual(p.tun_if.get_tx_stats(), 254)
# rekey - create new SAs and update the tunnel protection
np = copy.copy(p)
@ -2024,10 +2016,8 @@ class TestIpsec4TunProtect(TemplateIpsec,
self.unconfig_sa(p)
self.verify_tun_44(np, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 381)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 381)
self.assertEqual(p.tun_if.get_rx_stats(), 381)
self.assertEqual(p.tun_if.get_tx_stats(), 381)
# teardown
self.unconfig_protect(np)
@ -2074,10 +2064,8 @@ class TestIpsec4TunProtectUdp(TemplateIpsec,
p = self.ipv4_params
self.verify_tun_44(p, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 127)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 127)
self.assertEqual(p.tun_if.get_rx_stats(), 127)
self.assertEqual(p.tun_if.get_tx_stats(), 127)
def test_keepalive(self):
""" IPSEC NAT Keepalive """
@ -2168,10 +2156,8 @@ class TestIpsec4TunProtectTun(TemplateIpsec,
self.verify_tun_44(p, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 127)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 127)
self.assertEqual(p.tun_if.get_rx_stats(), 127)
self.assertEqual(p.tun_if.get_tx_stats(), 127)
# rekey - create new SAs and update the tunnel protection
np = copy.copy(p)
@ -2188,10 +2174,8 @@ class TestIpsec4TunProtectTun(TemplateIpsec,
self.unconfig_sa(p)
self.verify_tun_44(np, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 254)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 254)
self.assertEqual(p.tun_if.get_rx_stats(), 254)
self.assertEqual(p.tun_if.get_tx_stats(), 254)
# teardown
self.unconfig_protect(np)
@ -2275,10 +2259,8 @@ class TestIpsec6TunProtect(TemplateIpsec,
self.config_protect(p)
self.verify_tun_66(p, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 127)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 127)
self.assertEqual(p.tun_if.get_rx_stats(), 127)
self.assertEqual(p.tun_if.get_tx_stats(), 127)
# rekey - create new SAs and update the tunnel protection
np = copy.copy(p)
@ -2295,10 +2277,8 @@ class TestIpsec6TunProtect(TemplateIpsec,
self.unconfig_sa(p)
self.verify_tun_66(np, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 254)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 254)
self.assertEqual(p.tun_if.get_rx_stats(), 254)
self.assertEqual(p.tun_if.get_tx_stats(), 254)
# bounce the interface state
p.tun_if.admin_down()
@ -2342,10 +2322,8 @@ class TestIpsec6TunProtect(TemplateIpsec,
self.verify_tun_66(np3, np3, count=127)
self.verify_drop_tun_66(np, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 127*9)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 127*8)
self.assertEqual(p.tun_if.get_rx_stats(), 127*9)
self.assertEqual(p.tun_if.get_tx_stats(), 127*8)
self.unconfig_sa(np)
# teardown
@ -2363,10 +2341,8 @@ class TestIpsec6TunProtect(TemplateIpsec,
self.config_protect(p)
self.verify_tun_46(p, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 127)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 127)
self.assertEqual(p.tun_if.get_rx_stats(), 127)
self.assertEqual(p.tun_if.get_tx_stats(), 127)
# teardown
self.unconfig_protect(p)
@ -2447,10 +2423,8 @@ class TestIpsec6TunProtectTun(TemplateIpsec,
self.verify_tun_66(p, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 127)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 127)
self.assertEqual(p.tun_if.get_rx_stats(), 127)
self.assertEqual(p.tun_if.get_tx_stats(), 127)
# rekey - create new SAs and update the tunnel protection
np = copy.copy(p)
@ -2467,10 +2441,8 @@ class TestIpsec6TunProtectTun(TemplateIpsec,
self.unconfig_sa(p)
self.verify_tun_66(np, count=127)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 254)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 254)
self.assertEqual(p.tun_if.get_rx_stats(), 254)
self.assertEqual(p.tun_if.get_tx_stats(), 254)
# teardown
self.unconfig_protect(np)
@ -2630,29 +2602,23 @@ class TestIpsecItf4(TemplateIpsec,
self.config_protect(p)
self.verify_tun_44(p, count=n_pkts)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], n_pkts)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], n_pkts)
self.assertEqual(p.tun_if.get_rx_stats(), n_pkts)
self.assertEqual(p.tun_if.get_tx_stats(), n_pkts)
p.tun_if.admin_down()
self.verify_tun_dropped_44(p, count=n_pkts)
p.tun_if.admin_up()
self.verify_tun_44(p, count=n_pkts)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 3*n_pkts)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 2*n_pkts)
self.assertEqual(p.tun_if.get_rx_stats(), 3*n_pkts)
self.assertEqual(p.tun_if.get_tx_stats(), 2*n_pkts)
# it's a v6 packet when its encrypted
self.tun4_encrypt_node_name = "esp6-encrypt-tun"
self.verify_tun_64(p, count=n_pkts)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 4*n_pkts)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 3*n_pkts)
self.assertEqual(p.tun_if.get_rx_stats(), 4*n_pkts)
self.assertEqual(p.tun_if.get_tx_stats(), 3*n_pkts)
self.tun4_encrypt_node_name = "esp4-encrypt-tun"
@ -2675,10 +2641,8 @@ class TestIpsecItf4(TemplateIpsec,
self.unconfig_sa(p)
self.verify_tun_44(np, count=n_pkts)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], n_pkts)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], n_pkts)
self.assertEqual(p.tun_if.get_rx_stats(), n_pkts)
self.assertEqual(p.tun_if.get_tx_stats(), n_pkts)
# teardown
self.unconfig_protect(np)
@ -2735,10 +2699,8 @@ class TestIpsecItf4(TemplateIpsec,
policer.apply_vpp_config(p.tun_if.sw_if_index, True)
self.verify_tun_44(p, count=n_pkts)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], n_pkts)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], n_pkts)
self.assertEqual(p.tun_if.get_rx_stats(), n_pkts)
self.assertEqual(p.tun_if.get_tx_stats(), n_pkts)
stats = policer.get_stats()
@ -2942,29 +2904,23 @@ class TestIpsecItf6(TemplateIpsec,
self.config_protect(p)
self.verify_tun_66(p, count=n_pkts)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], n_pkts)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], n_pkts)
self.assertEqual(p.tun_if.get_rx_stats(), n_pkts)
self.assertEqual(p.tun_if.get_tx_stats(), n_pkts)
p.tun_if.admin_down()
self.verify_drop_tun_66(p, count=n_pkts)
p.tun_if.admin_up()
self.verify_tun_66(p, count=n_pkts)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 3*n_pkts)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 2*n_pkts)
self.assertEqual(p.tun_if.get_rx_stats(), 3*n_pkts)
self.assertEqual(p.tun_if.get_tx_stats(), 2*n_pkts)
# it's a v4 packet when its encrypted
self.tun6_encrypt_node_name = "esp4-encrypt-tun"
self.verify_tun_46(p, count=n_pkts)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], 4*n_pkts)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], 3*n_pkts)
self.assertEqual(p.tun_if.get_rx_stats(), 4*n_pkts)
self.assertEqual(p.tun_if.get_tx_stats(), 3*n_pkts)
self.tun6_encrypt_node_name = "esp6-encrypt-tun"
@ -2993,10 +2949,8 @@ class TestIpsecItf6(TemplateIpsec,
self.unconfig_sa(p)
self.verify_tun_66(np, count=n_pkts)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], n_pkts)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], n_pkts)
self.assertEqual(p.tun_if.get_rx_stats(), n_pkts)
self.assertEqual(p.tun_if.get_tx_stats(), n_pkts)
# teardown
self.unconfig_protect(np)
@ -3032,10 +2986,8 @@ class TestIpsecItf6(TemplateIpsec,
policer.apply_vpp_config(p.tun_if.sw_if_index, True)
self.verify_tun_66(p, count=n_pkts)
c = p.tun_if.get_rx_stats()
self.assertEqual(c['packets'], n_pkts)
c = p.tun_if.get_tx_stats()
self.assertEqual(c['packets'], n_pkts)
self.assertEqual(p.tun_if.get_rx_stats(), n_pkts)
self.assertEqual(p.tun_if.get_tx_stats(), n_pkts)
stats = policer.get_stats()

View File

@ -23,8 +23,8 @@ class StatsClientTestCase(VppTestCase):
def test_set_errors(self):
"""Test set errors"""
self.assertEqual(self.statistics.set_errors(), {})
self.assertEqual(self.statistics.get_counter('/err/ethernet-input/no'),
[0])
self.assertEqual(
self.statistics.get_counter('/err/ethernet-input/no error'), [0])
def test_client_fd_leak(self):
"""Test file descriptor count - VPP-1486"""

View File

@ -478,12 +478,12 @@ class VppInterface(metaclass=abc.ABCMeta):
return self.name
def get_rx_stats(self):
c = self.test.statistics.get_counter("^/if/rx$")
return c[0][self.sw_if_index]
return (self.test.statistics["/if/rx"]
[:, self.sw_if_index].sum_packets())
def get_tx_stats(self):
c = self.test.statistics.get_counter("^/if/tx$")
return c[0][self.sw_if_index]
return (self.test.statistics["/if/tx"]
[:, self.sw_if_index].sum_packets())
def set_l3_mtu(self, mtu):
self.test.vapi.sw_interface_set_mtu(self.sw_if_index, [mtu, 0, 0, 0])

View File

@ -83,5 +83,5 @@ class VppNeighbor(VppObject):
return ("%d:%s" % (self.sw_if_index, self.nbr_addr))
def get_stats(self):
c = self._test.statistics.get_counter("/net/adjacency")
c = self._test.statistics["/net/adjacency"]
return c[0][self.stats_index]