From 0dff5b36e45a94657f1046ff51ebb154f6cdec60 Mon Sep 17 00:00:00 2001 From: Pavel Kirienko Date: Thu, 27 Mar 2014 03:13:25 +0400 Subject: [PATCH] TransportStatsProvider --- .../protocol/transport_stats_provider.hpp | 34 ++++++++ .../src/protocol/transport_stats_provider.cpp | 35 ++++++++ .../dsdl_test/dsdl_uavcan_compilability.cpp | 2 +- libuavcan/test/node/test_node.hpp | 4 +- .../protocol/transport_stats_provider.cpp | 81 +++++++++++++++++++ 5 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 libuavcan/include/uavcan/protocol/transport_stats_provider.hpp create mode 100644 libuavcan/src/protocol/transport_stats_provider.cpp create mode 100644 libuavcan/test/protocol/transport_stats_provider.cpp diff --git a/libuavcan/include/uavcan/protocol/transport_stats_provider.hpp b/libuavcan/include/uavcan/protocol/transport_stats_provider.hpp new file mode 100644 index 0000000000..7723bd3c3e --- /dev/null +++ b/libuavcan/include/uavcan/protocol/transport_stats_provider.hpp @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#pragma once + +#include +#include +#include + +namespace uavcan +{ + +class TransportStatsProvider : Noncopyable +{ + typedef MethodBinder + GetTransportStatsCallback; + + ServiceServer srv_; + + void handleGetTransportStats(const protocol::GetTransportStats::Request&, + protocol::GetTransportStats::Response& resp) const; + +public: + explicit TransportStatsProvider(INode& node) + : srv_(node) + { } + + int start(); +}; + +} diff --git a/libuavcan/src/protocol/transport_stats_provider.cpp b/libuavcan/src/protocol/transport_stats_provider.cpp new file mode 100644 index 0000000000..be56f7f82e --- /dev/null +++ b/libuavcan/src/protocol/transport_stats_provider.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#include + +namespace uavcan +{ + +void TransportStatsProvider::handleGetTransportStats(const protocol::GetTransportStats::Request&, + protocol::GetTransportStats::Response& resp) const +{ + const TransferPerfCounter& perf = srv_.getNode().getDispatcher().getTransferPerfCounter(); + resp.transfer_errors = perf.getErrorCount(); + resp.transfers_tx = perf.getTxTransferCount(); + resp.transfers_rx = perf.getRxTransferCount(); + + const CanIOManager& canio = srv_.getNode().getDispatcher().getCanIOManager(); + for (int i = 0; i < canio.getNumIfaces(); i++) + { + const CanIfacePerfCounters can_perf = canio.getIfacePerfCounters(i); + protocol::CanIfaceStats stats; + stats.errors = can_perf.errors; + stats.frames_tx = can_perf.frames_tx; + stats.frames_rx = can_perf.frames_rx; + resp.can_iface_stats.push_back(stats); + } +} + +int TransportStatsProvider::start() +{ + return srv_.start(GetTransportStatsCallback(this, &TransportStatsProvider::handleGetTransportStats)); +} + +} diff --git a/libuavcan/test/dsdl_test/dsdl_uavcan_compilability.cpp b/libuavcan/test/dsdl_test/dsdl_uavcan_compilability.cpp index b82f4c9d68..aa6ce27ae2 100644 --- a/libuavcan/test/dsdl_test/dsdl_uavcan_compilability.cpp +++ b/libuavcan/test/dsdl_test/dsdl_uavcan_compilability.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/libuavcan/test/node/test_node.hpp b/libuavcan/test/node/test_node.hpp index db18cdfd92..b7bdca41a0 100644 --- a/libuavcan/test/node/test_node.hpp +++ b/libuavcan/test/node/test_node.hpp @@ -43,10 +43,12 @@ struct PairableCanDriver : public uavcan::ICanDriver, public uavcan::ICanIface PairableCanDriver* other; std::queue read_queue; std::queue loopback_queue; + uint64_t error_count; PairableCanDriver(uavcan::ISystemClock& clock) : clock(clock) , other(NULL) + , error_count(0) { } void linkTogether(PairableCanDriver* with) @@ -122,7 +124,7 @@ struct PairableCanDriver : public uavcan::ICanDriver, public uavcan::ICanIface int configureFilters(const uavcan::CanFilterConfig*, int) { return -1; } int getNumFilters() const { return 0; } - uint64_t getErrorCount() const { return 0; } + uint64_t getErrorCount() const { return error_count; } }; diff --git a/libuavcan/test/protocol/transport_stats_provider.cpp b/libuavcan/test/protocol/transport_stats_provider.cpp new file mode 100644 index 0000000000..13e365a8d1 --- /dev/null +++ b/libuavcan/test/protocol/transport_stats_provider.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#include +#include +#include "helpers.hpp" + + +TEST(TransportStatsProvider, Basic) +{ + InterlinkedTestNodesWithSysClock nodes; + + uavcan::TransportStatsProvider tsp(nodes.a); + + uavcan::GlobalDataTypeRegistry::instance().reset(); + uavcan::DefaultDataTypeRegistrator _reg1; + + ASSERT_LE(0, tsp.start()); + + ServiceClientWithCollector tsp_cln(nodes.b); + + /* + * First request + */ + ASSERT_LE(0, tsp_cln.call(1, uavcan::protocol::GetTransportStats::Request())); + ASSERT_LE(0, nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(1))); + + ASSERT_TRUE(tsp_cln.collector.result->isSuccessful()); + ASSERT_EQ(0, tsp_cln.collector.result->response.transfer_errors); + ASSERT_EQ(1, tsp_cln.collector.result->response.transfers_rx); + ASSERT_EQ(0, tsp_cln.collector.result->response.transfers_tx); + ASSERT_EQ(1, tsp_cln.collector.result->response.can_iface_stats.size()); + ASSERT_EQ(0, tsp_cln.collector.result->response.can_iface_stats[0].errors); + ASSERT_EQ(1, tsp_cln.collector.result->response.can_iface_stats[0].frames_rx); + ASSERT_EQ(0, tsp_cln.collector.result->response.can_iface_stats[0].frames_tx); + + /* + * Second request + */ + ASSERT_LE(0, tsp_cln.call(1, uavcan::protocol::GetTransportStats::Request())); + ASSERT_LE(0, nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(1))); + + ASSERT_EQ(0, tsp_cln.collector.result->response.transfer_errors); + ASSERT_EQ(2, tsp_cln.collector.result->response.transfers_rx); + ASSERT_EQ(1, tsp_cln.collector.result->response.transfers_tx); + ASSERT_EQ(1, tsp_cln.collector.result->response.can_iface_stats.size()); + ASSERT_EQ(0, tsp_cln.collector.result->response.can_iface_stats[0].errors); + ASSERT_EQ(2, tsp_cln.collector.result->response.can_iface_stats[0].frames_rx); + ASSERT_EQ(8, tsp_cln.collector.result->response.can_iface_stats[0].frames_tx); + + /* + * Sending a malformed frame, it must be registered as tranfer error + */ + uavcan::Frame frame(uavcan::protocol::GetTransportStats::DefaultDataTypeID, uavcan::TransferTypeServiceRequest, + 2, 1, 0, 0, true); + uavcan::CanFrame can_frame; + ASSERT_TRUE(frame.compile(can_frame)); + nodes.can_a.read_queue.push(can_frame); + + ASSERT_LE(0, nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(1))); + + /* + * Introducing a CAN driver error + */ + nodes.can_a.error_count = 72; + + /* + * Third request + */ + ASSERT_LE(0, tsp_cln.call(1, uavcan::protocol::GetTransportStats::Request())); + ASSERT_LE(0, nodes.spinBoth(uavcan::MonotonicDuration::fromMSec(1))); + + ASSERT_EQ(1, tsp_cln.collector.result->response.transfer_errors); // That broken frame + ASSERT_EQ(3, tsp_cln.collector.result->response.transfers_rx); + ASSERT_EQ(2, tsp_cln.collector.result->response.transfers_tx); + ASSERT_EQ(1, tsp_cln.collector.result->response.can_iface_stats.size()); + ASSERT_EQ(72, tsp_cln.collector.result->response.can_iface_stats[0].errors); + ASSERT_EQ(4, tsp_cln.collector.result->response.can_iface_stats[0].frames_rx); // Same here + ASSERT_EQ(16, tsp_cln.collector.result->response.can_iface_stats[0].frames_tx); +}