}
}
- /// \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.
/// \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());
}
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) {
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();
/// \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
// 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