mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-12 03:33:34 +08:00
CAN IO perf counters
This commit is contained in:
@@ -142,9 +142,9 @@ public:
|
||||
virtual int getNumFilters() const = 0;
|
||||
|
||||
/**
|
||||
* Continuously incrementing counter of detected hardware errors.
|
||||
* Continuously incrementing counter of hardware errors.
|
||||
*/
|
||||
virtual uint64_t getNumErrors() const = 0;
|
||||
virtual uint64_t getErrorCount() const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -110,22 +110,44 @@ public:
|
||||
|
||||
bool topPriorityHigherOrEqual(const CanFrame& rhs_frame) const;
|
||||
|
||||
uint32_t getNumRejectedFrames() const { return rejected_frames_cnt_; }
|
||||
uint32_t getRejectedFrameCount() const { return rejected_frames_cnt_; }
|
||||
|
||||
bool isEmpty() const { return queue_.isEmpty(); }
|
||||
};
|
||||
|
||||
|
||||
struct CanIfacePerfCounters
|
||||
{
|
||||
uint64_t frames_tx;
|
||||
uint64_t frames_rx;
|
||||
uint64_t errors;
|
||||
|
||||
CanIfacePerfCounters()
|
||||
: frames_tx(0)
|
||||
, frames_rx(0)
|
||||
, errors(0)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
class CanIOManager : Noncopyable
|
||||
{
|
||||
struct IfaceFrameCounters
|
||||
{
|
||||
uint64_t frames_tx;
|
||||
uint64_t frames_rx;
|
||||
|
||||
IfaceFrameCounters()
|
||||
: frames_tx(0)
|
||||
, frames_rx(0)
|
||||
{ }
|
||||
};
|
||||
|
||||
ICanDriver& driver_;
|
||||
ISystemClock& sysclock_;
|
||||
|
||||
CanTxQueue tx_queues_[MaxCanIfaces];
|
||||
|
||||
// Noncopyable
|
||||
CanIOManager(CanIOManager&);
|
||||
CanIOManager& operator=(CanIOManager&);
|
||||
IfaceFrameCounters counters_[MaxCanIfaces];
|
||||
|
||||
int sendToIface(int iface_index, const CanFrame& frame, MonotonicTime tx_deadline, CanIOFlags flags);
|
||||
int sendFromTxQueue(int iface_index);
|
||||
@@ -147,7 +169,7 @@ public:
|
||||
|
||||
int getNumIfaces() const;
|
||||
|
||||
uint64_t getNumErrors(int iface_index) const;
|
||||
CanIfacePerfCounters getIfacePerfCounters(int iface_index) const;
|
||||
|
||||
/**
|
||||
* Returns:
|
||||
|
||||
@@ -227,6 +227,10 @@ int CanIOManager::sendToIface(int iface_index, const CanFrame& frame, MonotonicT
|
||||
UAVCAN_TRACE("CanIOManager", "Send failed: code %i, iface %i, frame %s",
|
||||
res, iface_index, frame.toString().c_str());
|
||||
}
|
||||
if (res > 0)
|
||||
{
|
||||
counters_[iface_index].frames_tx += res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -266,15 +270,19 @@ int CanIOManager::getNumIfaces() const
|
||||
return std::min(std::max(num, 0), (int)MaxCanIfaces);
|
||||
}
|
||||
|
||||
uint64_t CanIOManager::getNumErrors(int iface_index) const
|
||||
CanIfacePerfCounters CanIOManager::getIfacePerfCounters(int iface_index) const
|
||||
{
|
||||
ICanIface* const iface = driver_.getIface(iface_index);
|
||||
if (iface == NULL || iface_index >= MaxCanIfaces || iface_index < 0)
|
||||
{
|
||||
assert(0);
|
||||
return std::numeric_limits<uint64_t>::max();
|
||||
return CanIfacePerfCounters();
|
||||
}
|
||||
return iface->getNumErrors() + tx_queues_[iface_index].getNumRejectedFrames();
|
||||
CanIfacePerfCounters cnt;
|
||||
cnt.errors = iface->getErrorCount() + tx_queues_[iface_index].getRejectedFrameCount();
|
||||
cnt.frames_rx = counters_[iface_index].frames_rx;
|
||||
cnt.frames_tx = counters_[iface_index].frames_tx;
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int CanIOManager::send(const CanFrame& frame, MonotonicTime tx_deadline, MonotonicTime blocking_deadline,
|
||||
@@ -406,6 +414,10 @@ int CanIOManager::receive(CanRxFrame& out_frame, MonotonicTime blocking_deadline
|
||||
continue;
|
||||
}
|
||||
out_frame.iface_index = i;
|
||||
if ((res > 0) && !(out_flags & CanIOFlagLoopback))
|
||||
{
|
||||
counters_[i].frames_rx += 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ struct PairableCanDriver : public uavcan::ICanDriver, public uavcan::ICanIface
|
||||
|
||||
int configureFilters(const uavcan::CanFilterConfig*, int) { return -1; }
|
||||
int getNumFilters() const { return 0; }
|
||||
uint64_t getNumErrors() const { return 0; }
|
||||
uint64_t getErrorCount() const { return 0; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
int configureFilters(const uavcan::CanFilterConfig*, int) { return -1; }
|
||||
// cppcheck-suppress unusedFunction
|
||||
int getNumFilters() const { return 0; }
|
||||
uint64_t getNumErrors() const { return num_errors; }
|
||||
uint64_t getErrorCount() const { return num_errors; }
|
||||
};
|
||||
|
||||
class CanDriverMock : public uavcan::ICanDriver
|
||||
|
||||
@@ -91,7 +91,7 @@ TEST(CanIOManager, Reception)
|
||||
EXPECT_EQ(0, flags);
|
||||
|
||||
/*
|
||||
* Errors
|
||||
* Perf counters
|
||||
*/
|
||||
driver.select_failure = true;
|
||||
EXPECT_EQ(-1, iomgr.receive(frame, uavcan::MonotonicTime(), flags));
|
||||
@@ -103,8 +103,14 @@ TEST(CanIOManager, Reception)
|
||||
|
||||
driver.ifaces.at(0).num_errors = 9000;
|
||||
driver.ifaces.at(1).num_errors = 100500;
|
||||
EXPECT_EQ(9000, iomgr.getNumErrors(0));
|
||||
EXPECT_EQ(100500, iomgr.getNumErrors(1));
|
||||
EXPECT_EQ(9000, iomgr.getIfacePerfCounters(0).errors);
|
||||
EXPECT_EQ(100500, iomgr.getIfacePerfCounters(1).errors);
|
||||
|
||||
EXPECT_EQ(3, iomgr.getIfacePerfCounters(0).frames_rx);
|
||||
EXPECT_EQ(3, iomgr.getIfacePerfCounters(1).frames_rx);
|
||||
|
||||
EXPECT_EQ(0, iomgr.getIfacePerfCounters(0).frames_tx);
|
||||
EXPECT_EQ(0, iomgr.getIfacePerfCounters(1).frames_tx);
|
||||
}
|
||||
|
||||
TEST(CanIOManager, Transmission)
|
||||
@@ -149,8 +155,8 @@ TEST(CanIOManager, Transmission)
|
||||
EXPECT_EQ(0, clockmock.utc);
|
||||
EXPECT_TRUE(driver.ifaces.at(0).tx.empty());
|
||||
EXPECT_TRUE(driver.ifaces.at(1).tx.empty());
|
||||
EXPECT_EQ(0, iomgr.getNumErrors(0));
|
||||
EXPECT_EQ(0, iomgr.getNumErrors(1));
|
||||
EXPECT_EQ(0, iomgr.getIfacePerfCounters(0).errors);
|
||||
EXPECT_EQ(0, iomgr.getIfacePerfCounters(1).errors);
|
||||
|
||||
/*
|
||||
* TX Queue basics
|
||||
@@ -204,9 +210,9 @@ TEST(CanIOManager, Transmission)
|
||||
// Final checks
|
||||
EXPECT_TRUE(driver.ifaces.at(0).tx.empty());
|
||||
EXPECT_TRUE(driver.ifaces.at(1).tx.empty());
|
||||
EXPECT_EQ(0, pool.getNumUsedBlocks()); // Make sure the memory was properly released
|
||||
EXPECT_EQ(1, iomgr.getNumErrors(0)); // This is because of expired frame[0]
|
||||
EXPECT_EQ(0, iomgr.getNumErrors(1));
|
||||
EXPECT_EQ(0, pool.getNumUsedBlocks()); // Make sure the memory was properly released
|
||||
EXPECT_EQ(1, iomgr.getIfacePerfCounters(0).errors); // This is because of expired frame[0]
|
||||
EXPECT_EQ(0, iomgr.getIfacePerfCounters(1).errors);
|
||||
|
||||
/*
|
||||
* TX Queue updates from receive() call
|
||||
@@ -254,8 +260,8 @@ TEST(CanIOManager, Transmission)
|
||||
EXPECT_EQ(1200, clockmock.utc);
|
||||
EXPECT_TRUE(driver.ifaces.at(0).tx.empty());
|
||||
EXPECT_TRUE(driver.ifaces.at(1).tx.empty());
|
||||
EXPECT_EQ(1, iomgr.getNumErrors(0));
|
||||
EXPECT_EQ(1, iomgr.getNumErrors(1)); // This is because of rejected frame[1]
|
||||
EXPECT_EQ(1, iomgr.getIfacePerfCounters(0).errors);
|
||||
EXPECT_EQ(1, iomgr.getIfacePerfCounters(1).errors); // This is because of rejected frame[1]
|
||||
|
||||
/*
|
||||
* Error handling
|
||||
@@ -287,6 +293,15 @@ TEST(CanIOManager, Transmission)
|
||||
EXPECT_TRUE(driver.ifaces.at(1).matchAndPopTx(frames[0], 2200));
|
||||
EXPECT_EQ(0, pool.getNumUsedBlocks()); // All transmitted
|
||||
ASSERT_EQ(0, flags);
|
||||
|
||||
/*
|
||||
* Perf counters
|
||||
*/
|
||||
EXPECT_EQ(1, iomgr.getIfacePerfCounters(0).frames_rx);
|
||||
EXPECT_EQ(1, iomgr.getIfacePerfCounters(1).frames_rx);
|
||||
|
||||
EXPECT_EQ(6, iomgr.getIfacePerfCounters(0).frames_tx);
|
||||
EXPECT_EQ(8, iomgr.getIfacePerfCounters(1).frames_tx);
|
||||
}
|
||||
|
||||
TEST(CanIOManager, Loopback)
|
||||
@@ -335,6 +350,16 @@ TEST(CanIOManager, Loopback)
|
||||
ASSERT_EQ(uavcan::CanIOFlagLoopback, flags);
|
||||
ASSERT_TRUE(rfr1 == fr1);
|
||||
ASSERT_TRUE(rfr2 == fr2);
|
||||
|
||||
/*
|
||||
* Perf counters
|
||||
* Loopback frames are not registered as RX
|
||||
*/
|
||||
EXPECT_EQ(0, iomgr.getIfacePerfCounters(0).frames_rx);
|
||||
EXPECT_EQ(0, iomgr.getIfacePerfCounters(1).frames_rx);
|
||||
|
||||
EXPECT_EQ(3, iomgr.getIfacePerfCounters(0).frames_tx);
|
||||
EXPECT_EQ(0, iomgr.getIfacePerfCounters(1).frames_tx);
|
||||
}
|
||||
|
||||
TEST(CanIOManager, Size)
|
||||
|
||||
@@ -112,7 +112,7 @@ TEST(CanTxQueue, TxQueue)
|
||||
|
||||
// Out of free memory now
|
||||
|
||||
EXPECT_EQ(0, queue.getNumRejectedFrames());
|
||||
EXPECT_EQ(0, queue.getRejectedFrameCount());
|
||||
EXPECT_EQ(4, getQueueLength(queue));
|
||||
EXPECT_TRUE(isInQueue(queue, f0));
|
||||
EXPECT_TRUE(isInQueue(queue, f1));
|
||||
@@ -137,7 +137,7 @@ TEST(CanTxQueue, TxQueue)
|
||||
EXPECT_TRUE(isInQueue(queue, f2));
|
||||
EXPECT_FALSE(isInQueue(queue, f1));
|
||||
EXPECT_EQ(4, getQueueLength(queue));
|
||||
EXPECT_EQ(2, queue.getNumRejectedFrames());
|
||||
EXPECT_EQ(2, queue.getRejectedFrameCount());
|
||||
EXPECT_EQ(f0, queue.peek()->frame); // Check the priority
|
||||
|
||||
queue.push(f5, tsMono(600), CanTxQueue::Persistent, flags); // Will override f0 (rest are presistent)
|
||||
@@ -159,7 +159,7 @@ TEST(CanTxQueue, TxQueue)
|
||||
EXPECT_TRUE(queue.topPriorityHigherOrEqual(f5a));
|
||||
EXPECT_EQ(4, getQueueLength(queue));
|
||||
EXPECT_EQ(4, pool32.getNumUsedBlocks());
|
||||
EXPECT_EQ(5, queue.getNumRejectedFrames());
|
||||
EXPECT_EQ(5, queue.getRejectedFrameCount());
|
||||
EXPECT_TRUE(isInQueue(queue, f2));
|
||||
EXPECT_TRUE(isInQueue(queue, f3));
|
||||
EXPECT_TRUE(isInQueue(queue, f4));
|
||||
@@ -173,19 +173,19 @@ TEST(CanTxQueue, TxQueue)
|
||||
queue.push(f0, tsMono(800), CanTxQueue::Volatile, flags); // Will replace f4 which is expired now
|
||||
EXPECT_TRUE(isInQueue(queue, f0));
|
||||
EXPECT_FALSE(isInQueue(queue, f4));
|
||||
EXPECT_EQ(6, queue.getNumRejectedFrames());
|
||||
EXPECT_EQ(6, queue.getRejectedFrameCount());
|
||||
|
||||
clockmock.monotonic = 1001;
|
||||
queue.push(f5, tsMono(2000), CanTxQueue::Volatile, flags); // Entire queue is expired
|
||||
EXPECT_TRUE(isInQueue(queue, f5));
|
||||
EXPECT_EQ(1, getQueueLength(queue)); // Just one entry left - f5
|
||||
EXPECT_EQ(1, pool32.getNumUsedBlocks()); // Make sure there is no leaks
|
||||
EXPECT_EQ(10, queue.getNumRejectedFrames());
|
||||
EXPECT_EQ(10, queue.getRejectedFrameCount());
|
||||
|
||||
queue.push(f0, tsMono(1000), CanTxQueue::Persistent, flags); // This entry is already expired
|
||||
EXPECT_EQ(1, getQueueLength(queue));
|
||||
EXPECT_EQ(1, pool32.getNumUsedBlocks());
|
||||
EXPECT_EQ(11, queue.getNumRejectedFrames());
|
||||
EXPECT_EQ(11, queue.getRejectedFrameCount());
|
||||
|
||||
/*
|
||||
* Removing
|
||||
@@ -212,7 +212,7 @@ TEST(CanTxQueue, TxQueue)
|
||||
|
||||
EXPECT_EQ(0, getQueueLength(queue)); // Final state checks
|
||||
EXPECT_EQ(0, pool32.getNumUsedBlocks());
|
||||
EXPECT_EQ(11, queue.getNumRejectedFrames());
|
||||
EXPECT_EQ(11, queue.getRejectedFrameCount());
|
||||
EXPECT_FALSE(queue.peek());
|
||||
EXPECT_FALSE(queue.topPriorityHigherOrEqual(f0));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user