Browse Source

[3183] Clean Reply packet storage every one second.

Marcin Siodelski 11 years ago
parent
commit
d130980f51

+ 19 - 4
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());
     }
 

+ 40 - 0
tests/tools/perfdhcp/test_control.cc

@@ -98,6 +98,38 @@ TestControl::TestControl() {
 }
 
 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) {
         isc_throw(BadValue, "NULL pointers must not be specified as arguments"
@@ -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();
 

+ 10 - 0
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

+ 19 - 1
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