From: Marcin Siodelski Date: Thu, 10 Oct 2013 14:25:36 +0000 (+0200) Subject: [3183] Clean Reply packet storage every one second. X-Git-Tag: bind10-1.2.0beta1-release~102^2~36^2~1^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=d130980f515cc5cfab65df8dd0944b56d5fbcdea;p=thirdparty%2Fkea.git [3183] Clean Reply packet storage every one second. --- diff --git a/tests/tools/perfdhcp/packet_storage.h b/tests/tools/perfdhcp/packet_storage.h index 96c66c9405..45d01ccf4f 100644 --- a/tests/tools/perfdhcp/packet_storage.h +++ b/tests/tools/perfdhcp/packet_storage.h @@ -73,9 +73,24 @@ public: } } - /// \brief Removes all packets from the storage. - void clear() { - storage_.clear(); + /// \brief Removes packets from the storage. + /// + /// It is possible to specify a number of packets to be removed + /// from a storage. Packets are removed from the beginning of the + /// storage. If specified number is greater than the size of the + /// storage, all packets are removed. + /// + /// @param num A number of packets to be removed. If omitted, + /// all packets will be removed. + void clear(const uint64_t num = 0) { + if (num != 0) { + PacketContainerIterator last = storage_.begin(); + std::advance(last, num > size() ? size() : num); + current_pointer_ = storage_.erase(storage_.begin(), last); + } else { + storage_.clear(); + current_pointer_ = storage_.begin(); + } } /// \brief Checks if the storage has no packets. @@ -128,7 +143,7 @@ public: /// \brief Returns number of packets in the storage. /// /// \return number of packets in the storage. - uint32_t size() const { + uint64_t size() const { return (storage_.size()); } diff --git a/tests/tools/perfdhcp/test_control.cc b/tests/tools/perfdhcp/test_control.cc index f3db3befe3..a2a4cd514f 100644 --- a/tests/tools/perfdhcp/test_control.cc +++ b/tests/tools/perfdhcp/test_control.cc @@ -97,6 +97,38 @@ TestControl::TestControl() { reset(); } +void +TestControl::cleanCachedPackets() { + CommandOptions& options = CommandOptions::instance(); + // When Renews are not sent, Reply packets are not cached so there + // is nothing to do. + if (options.getRenewRate() == 0) { + return; + } + + static boost::posix_time::ptime last_clean = + microsec_clock::universal_time(); + + // Check how much time has passed since last cleanup. + time_period time_since_clean(last_clean, + microsec_clock::universal_time()); + // Cleanup every 1 second. + if (time_since_clean.length().total_seconds() >= 1) { + // Calculate how many cached packets to remove. Actually we could + // just leave enough packets to handle Renews for 1 second but + // since we want to randomize leases to be renewed so leave 5 + // times more packets to randomize from. + // @todo The cache size might be controlled from the command line. + if (reply_storage_.size() > 5 * options.getRenewRate()) { + reply_storage_.clear(reply_storage_.size() - + 5 * options.getRenewRate()); + } + // Remember when we performed a cleanup for the last time. + // We want to do the next cleanup not earlier than in one second. + last_clean = microsec_clock::universal_time(); + } +} + void TestControl::copyIaOptions(const Pkt6Ptr& pkt_from, Pkt6Ptr& pkt_to) { if (!pkt_from || !pkt_to) { @@ -1314,6 +1346,14 @@ TestControl::run() { if (options.getReportDelay() > 0) { printIntermediateStats(); } + + // If we are sending Renews to the server, the Reply packets are cached + // so as leases for which we send Renews can be idenitfied. The major + // issue with this approach is that most of the time we are caching + // more packets than we actually need. This function removes excessive + // Reply messages to reduce the memory and CPU utilization. Note that + // searches in the long list of Reply packets increases CPU utilization. + cleanCachedPackets(); } printStats(); diff --git a/tests/tools/perfdhcp/test_control.h b/tests/tools/perfdhcp/test_control.h index 136fa9e5f5..db0f21850c 100644 --- a/tests/tools/perfdhcp/test_control.h +++ b/tests/tools/perfdhcp/test_control.h @@ -300,6 +300,16 @@ protected: /// \return true if any of the exit conditions is fulfilled. bool checkExitConditions() const; + /// \brief Removes cached DHCPv6 Reply packets every second. + /// + /// This function wipes cached Reply packets from the storage. + /// The number of packets left in the storage after the call + /// to this function should guarantee that the Renew packets + /// can be sent at the given rate. Note that the Renew packets + /// are generated for the existing leases, represented here as + /// replies from the server. + void cleanCachedPackets(); + /// \brief Creates IPv6 packet using options from Reply packet. /// /// \param reply An instance of the Reply packet which contents should diff --git a/tests/tools/perfdhcp/tests/packet_storage_unittest.cc b/tests/tools/perfdhcp/tests/packet_storage_unittest.cc index 10b83fbfae..6a8a316bc2 100644 --- a/tests/tools/perfdhcp/tests/packet_storage_unittest.cc +++ b/tests/tools/perfdhcp/tests/packet_storage_unittest.cc @@ -135,11 +135,29 @@ TEST_F(PacketStorageTest, getNextAndRandom) { // This test verifies that all packets are removed from the storage when // clear() function is invoked. -TEST_F(PacketStorageTest, clear) { +TEST_F(PacketStorageTest, clearAll) { ASSERT_EQ(STORAGE_SIZE, storage_.size()); ASSERT_NO_THROW(storage_.clear()); EXPECT_TRUE(storage_.empty()); } +// This test verifies that a set of packets can be removed from the +// storage when a number of packets to be removed is specified. If +// number of packets to be removed exceeds the storage size, all +// packets should be removed. +TEST_F(PacketStorageTest, clear) { + // Initially storage should have 20 elements. + ASSERT_EQ(STORAGE_SIZE, storage_.size()); + // Remove 10 of them. + ASSERT_NO_THROW(storage_.clear(10)); + // We should have 10 remaining. + ASSERT_EQ(10, storage_.size()); + + // Try to remove more elements that actually is. It + // should result in removal of all elements. + ASSERT_NO_THROW(storage_.clear(15)); + EXPECT_TRUE(storage_.empty()); +} + } // anonymous namespace