]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1703] perfdhcp -x l: printLeases()
authorAndrei Pavel <andrei@isc.org>
Mon, 15 Feb 2021 12:06:25 +0000 (14:06 +0200)
committerAndrei Pavel <andrei@isc.org>
Wed, 17 Feb 2021 07:03:02 +0000 (09:03 +0200)
src/bin/perfdhcp/avalanche_scen.cc
src/bin/perfdhcp/basic_scen.cc
src/bin/perfdhcp/command_options.cc
src/bin/perfdhcp/stats_mgr.cc
src/bin/perfdhcp/stats_mgr.h
src/bin/perfdhcp/test_control.cc

index 11a793f8a47cf07f5660fa7569c3d11d71f911a6..a4b187869a7cc61dbe47c1a7a26f9b6f4fd93901 100644 (file)
@@ -171,6 +171,11 @@ AvalancheScen::run() {
         std::cout << "Interrupted" << std::endl;
     }
 
+    // Print any received leases.
+    if (options_.testDiags('l')) {
+        stats_mgr.printLeases();
+    }
+
     // Calculate total stats.
     int total_sent_pkts = total_resent_; // This holds sent + resent packets counts.
     int total_rcvd_pkts = 0;  // This holds received packets count.
@@ -193,5 +198,5 @@ AvalancheScen::run() {
     return (0);
 }
 
-}
-}
+}  // namespace perfdhcp
+}  // namespace isc
index 6b7bcc23dd2fb5e0486d705a62df65a15dfb60bc..5469310db42ae556715cc71062059f3eda10808d 100644 (file)
@@ -237,12 +237,16 @@ BasicScen::run() {
         tc_.printTemplates();
     }
 
+    // Print any received leases.
+    if (options_.testDiags('l')) {
+        stats_mgr.printLeases();
+    }
+
     int ret_code = 0;
     // Check if any packet drops occurred.
     ret_code = stats_mgr.droppedPackets() ? 3 : 0;
     return (ret_code);
 }
 
-
-}
-}
+}  // namespace perfdhcp
+}  // namespace isc
index 02e1573b9440bf259520e82979dbafa8e3864373..31053f22f861c26796b488dae2c71838817ccd44 100644 (file)
@@ -1281,10 +1281,11 @@ CommandOptions::usage() const {
         "-x<diagnostic-selector>: Include extended diagnostics in the output.\n"
         "    <diagnostic-selector> is a string of single-keywords specifying\n"
         "    the operations for which verbose output is desired.  The selector\n"
-        "    keyletters are:\n"
+        "    key letters are:\n"
         "   * 'a': print the decoded command line arguments\n"
         "   * 'e': print the exit reason\n"
         "   * 'i': print rate processing details\n"
+        "   * 'l': print received leases\n"
         "   * 's': print first server-id\n"
         "   * 't': when finished, print timers of all successful exchanges\n"
         "   * 'T': when finished, print templates\n"
index 899686c49daa98589a53cf2e9cd37292abd44027..4d312de6b65b18e83e710c574020e683fed35feb 100644 (file)
@@ -6,12 +6,46 @@
 
 #include <config.h>
 
+#include <dhcp/dhcp4.h>
+#include <dhcp/dhcp6.h>
+#include <dhcp/duid.h>
+#include <dhcp/option6_iaaddr.h>
+#include <dhcp/option6_iaprefix.h>
+#include <dhcp/pkt4.h>
 #include <perfdhcp/stats_mgr.h>
+#include <perfdhcp/test_control.h>
 
+using isc::dhcp::DHO_DHCP_CLIENT_IDENTIFIER;
+using isc::dhcp::DUID;
+using isc::dhcp::Option6IAAddr;
+using isc::dhcp::Option6IAAddrPtr;
+using isc::dhcp::Option6IAPrefix;
+using isc::dhcp::Option6IAPrefixPtr;
+using isc::dhcp::OptionPtr;
+using isc::dhcp::Pkt4;
+using isc::dhcp::Pkt4Ptr;
+using isc::dhcp::PktPtr;
 
 namespace isc {
 namespace perfdhcp {
 
+int dhcpVersion(ExchangeType const exchange_type) {
+    switch (exchange_type) {
+    case ExchangeType::DO:
+    case ExchangeType::RA:
+    case ExchangeType::RNA:
+        return 4;
+    case ExchangeType::SA:
+    case ExchangeType::RR:
+    case ExchangeType::RN:
+    case ExchangeType::RL:
+        return 6;
+    default:
+        isc_throw(BadValue,
+                  "unrecognized exchange type '" << exchange_type << "'");
+    }
+}
+
 std::ostream& operator<<(std::ostream& os, ExchangeType xchg_type)
 {
     switch(xchg_type) {
@@ -64,8 +98,8 @@ ExchangeStats::ExchangeStats(const ExchangeType xchg_type,
 }
 
 void
-ExchangeStats::updateDelays(const dhcp::PktPtr& sent_packet,
-                            const dhcp::PktPtr& rcvd_packet) {
+ExchangeStats::updateDelays(const PktPtr& sent_packet,
+                            const PktPtr& rcvd_packet) {
     if (!sent_packet) {
         isc_throw(BadValue, "Sent packet is null");
     }
@@ -114,8 +148,8 @@ ExchangeStats::updateDelays(const dhcp::PktPtr& sent_packet,
     sum_delay_squared_ += delta * delta;
 }
 
-dhcp::PktPtr
-ExchangeStats::matchPackets(const dhcp::PktPtr& rcvd_packet) {
+PktPtr
+ExchangeStats::matchPackets(const PktPtr& rcvd_packet) {
     using namespace boost::posix_time;
 
     if (!rcvd_packet) {
@@ -128,7 +162,7 @@ ExchangeStats::matchPackets(const dhcp::PktPtr& rcvd_packet) {
         // that the received packet we got has no corresponding
         // sent packet so orphans counter has to be updated.
         ++orphans_;
-        return(dhcp::PktPtr());
+        return(PktPtr());
     } else if (next_sent_ == sent_packets_.end()) {
         // Even if there are still many unmatched packets on the
         // list we might hit the end of it because of unordered
@@ -246,13 +280,13 @@ ExchangeStats::matchPackets(const dhcp::PktPtr& rcvd_packet) {
         // If we are here, it means that both ordered lookup and
         // unordered lookup failed. Searched packet is not on the list.
         ++orphans_;
-        return(dhcp::PktPtr());
+        return(PktPtr());
     }
 
     // Packet is matched so we count it. We don't count unmatched packets
     // as they are counted as orphans with a separate counter.
     ++rcvd_packets_num_;
-    dhcp::PktPtr sent_packet(*next_sent_);
+    PktPtr sent_packet(*next_sent_);
     // If packet was found, we assume it will be never searched
     // again. We want to delete this packet from the list to
     // improve performance of future searches.
@@ -279,7 +313,7 @@ ExchangeStats::printTimestamps() {
     for (PktListIterator it = rcvd_packets_.begin();
          it != rcvd_packets_.end();
          ++it) {
-        dhcp::PktPtr rcvd_packet = *it;
+        PktPtr rcvd_packet = *it;
         PktListTransidHashIndex& idx =
             archived_packets_.template get<1>();
         std::pair<PktListTransidHashIterator,
@@ -290,7 +324,7 @@ ExchangeStats::printTimestamps() {
              ++it_archived) {
             if ((*it_archived)->getTransid() ==
                 rcvd_packet->getTransid()) {
-                dhcp::PktPtr sent_packet = *it_archived;
+                PktPtr sent_packet = *it_archived;
                 // Get sent and received packet times.
                 ptime sent_time = sent_packet->getTimestamp();
                 ptime rcvd_time = rcvd_packet->getTimestamp();
@@ -322,9 +356,9 @@ StatsMgr::StatsMgr(CommandOptions& options) :
     boot_time_(boost::posix_time::microsec_clock::universal_time())
 {
     // Check if packet archive mode is required. If user
-    // requested diagnostics option -x t we have to enable
+    // requested diagnostics option -x l or -x t we have to enable
     // it so as StatsMgr preserves all packets.
-    archive_enabled_ = options.testDiags('t') ? true : false;
+    archive_enabled_ = options.testDiags('l') || options.testDiags('t');
 
     if (options.getIpVersion() == 4) {
         addExchangeStats(ExchangeType::DO, options.getDropTime()[0]);
@@ -351,7 +385,84 @@ StatsMgr::StatsMgr(CommandOptions& options) :
         addCustomCounter("shortwait", "Short waits for packets");
     }
 }
-int ExchangeStats::malformed_pkts_{0};
 
+std::string
+ExchangeStats::receivedLeases() const {
+    // Get DHCP version.
+    int const v(dhcpVersion(xchg_type_));
+
+    std::stringstream result;
+    // Iterate through all received packets.
+    for (PktPtr const& packet : rcvd_packets_) {
+
+        // Get client identifier.
+        if (v == 4) {
+            OptionPtr const& client_id_option(
+                packet->getOption(DHO_DHCP_CLIENT_IDENTIFIER));
+            if (client_id_option) {
+                result << TestControl::vector2Hex(client_id_option->getData());
+            }
+        } else if (v == 6) {
+            OptionPtr const& client_id_option(packet->getOption(D6O_CLIENTID));
+            if (client_id_option) {
+                result << DUID(client_id_option->getData()).toText();
+            }
+        } else {
+            isc_throw(BadValue, "unrecognized DHCP version '" << v << "'");
+        }
+        result << ',';
+
+        // Get address.
+        if (v == 4) {
+            Pkt4Ptr const& packet4(boost::dynamic_pointer_cast<Pkt4>(packet));
+            if (packet4) {
+                result << packet4->getYiaddr().toText();
+            }
+        } else if (v == 6) {
+            OptionPtr const& option(packet->getOption(D6O_IA_NA));
+            if (option) {
+                Option6IAAddrPtr const& iaaddr(
+                    boost::dynamic_pointer_cast<Option6IAAddr>(
+                        option->getOption(D6O_IAADDR)));
+                if (iaaddr) {
+                    result << iaaddr->getAddress().toText();
+                }
+            }
+        }
+        result << ',';
+
+        // Get prefix.
+        OptionPtr const& option(packet->getOption(D6O_IA_PD));
+        if (option) {
+            Option6IAPrefixPtr const& iaprefix(
+                boost::dynamic_pointer_cast<Option6IAPrefix>(
+                    option->getOption(D6O_IAPREFIX)));
+            if (iaprefix) {
+                result << iaprefix->getAddress().toText();
+            }
+        }
+
+        result << std::endl;
+    }
+
+    return result.str();
 }
+
+void
+ExchangeStats::printLeases() const {
+    std::cout << receivedLeases() << std::endl;
 }
+
+void StatsMgr::printLeases() const {
+    for (auto const& exchange : exchanges_) {
+        std::cout << "***Leases for " << exchange.first << "***" << std::endl;
+        std::cout << "client_id,adrress,prefix" << std::endl;
+        exchange.second->printLeases();
+        std::cout << std::endl;
+    }
+}
+
+int ExchangeStats::malformed_pkts_{0};
+
+}  // namespace perfdhcp
+}  // namespace isc
index 03741c633cbda47db9407e6101e8568b44719f42..b7a7d0fec46767c6066bbcb4fa6798c48cc06bce 100644 (file)
@@ -39,6 +39,13 @@ enum class ExchangeType {
     RL   ///< DHCPv6 RELEASE-REPLY
 };
 
+/// \brief Get the DHCP version that fits the exchange type.
+///
+/// \param exchange_type exchange type that will determine the version
+/// \throw isc::BadValue exchange type is unrecognized
+/// \return DHCP version: 4 or 6
+int dhcpVersion(ExchangeType const exchange_type);
+
 /// \brief Return name of the exchange.
 ///
 /// Function returns name of the specified exchange type.
@@ -555,6 +562,19 @@ public:
         return(std::make_tuple(sent_packets_.begin(), sent_packets_.end()));
     }
 
+    /// \brief Return the list of received leases in CSV format as string.
+    ///
+    /// Depending exchange type, it can apply to
+    /// potential leases received in offers and advertisements,
+    /// committed leases received in acknowledgements and replies,
+    /// renewed or released leases.
+    ///
+    /// \return multiline string of received leases in CSV format
+    std::string receivedLeases() const;
+
+    /// \brief Print the list of received leases.
+    void printLeases() const;
+
     static int malformed_pkts_;
 
 // Private stuff of ExchangeStats class
@@ -1159,6 +1179,9 @@ public:
         }
     }
 
+    /// \brief Delegate to all exchanges to print their leases.
+    void printLeases() const;
+
     /// \brief Print names and values of custom counters.
     ///
     /// Method prints names and values of custom counters. Custom counters
index 6f4ca935ff88d50fd29dd556dc43a792b2aafda8..cb973e4cc0d0a8ef9e59123610154019d0febebc 100644 (file)
@@ -698,7 +698,7 @@ TestControl::printStats() const {
 
 std::string
 TestControl::vector2Hex(const std::vector<uint8_t>& vec,
-                        const std::string& separator /* ="" */) {
+                        const std::string& separator /* = "" */) {
     std::ostringstream stream;
     for (std::vector<uint8_t>::const_iterator it = vec.begin();
          it != vec.end();