]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1119] implement use case: perfdhcp -4 -F<rate>
authorAndrei Pavel <andrei@isc.org>
Tue, 25 May 2021 15:21:43 +0000 (18:21 +0300)
committerAndrei Pavel <andrei@isc.org>
Tue, 22 Jun 2021 07:43:13 +0000 (10:43 +0300)
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
src/bin/perfdhcp/test_control.h

index 4556030c014fb62c04c0f471404f462cf95ceccb..570939cdbf8b47368fb2c3598cb0ea6ad3fa0e49 100644 (file)
@@ -8,7 +8,6 @@
 
 #include <perfdhcp/basic_scen.h>
 
-
 #include <boost/date_time/posix_time/posix_time.hpp>
 
 using namespace std;
@@ -178,7 +177,7 @@ BasicScen::run() {
 
             // Send multiple renews to satisfy the desired rate.
             if (options_.getIpVersion() == 4) {
-                tc_.sendMultipleRequests(renew_packets_due);
+                tc_.sendMultipleMessages(DHCPREQUEST, renew_packets_due);
             } else {
                 tc_.sendMultipleMessages6(DHCPV6_RENEW, renew_packets_due);
             }
@@ -186,11 +185,16 @@ BasicScen::run() {
 
         // If -F<release-rate> option was specified we have to check how many
         // Release messages should be sent to catch up with a desired rate.
-        if ((options_.getIpVersion() == 6) && (options_.getReleaseRate() != 0)) {
+        if (options_.getReleaseRate() != 0) {
             uint64_t release_packets_due =
                 release_rate_control_.getOutboundMessageCount(!tc_.exit_time_.is_not_a_date_time());
             // Send Release messages.
-            tc_.sendMultipleMessages6(DHCPV6_RELEASE, release_packets_due);
+
+            if (options_.getIpVersion() == 4) {
+                tc_.sendMultipleMessages(DHCPRELEASE, release_packets_due);
+            } else {
+                tc_.sendMultipleMessages6(DHCPV6_RELEASE, release_packets_due);
+            }
         }
 
         // Report delay means that user requested printing number
index bd6296fa471b81fc86c16bda91e37e9ff56bdb40..3c591303f0b95b3aa101eb8e850c6cfa5d207072 100644 (file)
@@ -920,8 +920,6 @@ CommandOptions::validate() {
           "-6 (IPv6) must be set to use -c");
     check(getIpVersion() == 4 && isUseRelayedV6(),
           "Can't use -4 with -A, it's a V6 only option.");
-    check((getIpVersion() != 6) && (getReleaseRate() != 0),
-          "-F<release-rate> may be used with -6 (IPv6) only");
     check((getExchangeMode() == DO_SA) && (getNumRequests().size() > 1),
           "second -n<num-request> is not compatible with -i");
     check((getIpVersion() == 4) && !getLeaseType().is(LeaseType::ADDRESS),
index 4a7c5a6711d1c7a3f8e963f3fce2c16d794e19d5..1563588f65463a720872c211d5acd9be836b1910 100644 (file)
@@ -34,6 +34,7 @@ int dhcpVersion(ExchangeType const exchange_type) {
     case ExchangeType::DO:
     case ExchangeType::RA:
     case ExchangeType::RNA:
+    case ExchangeType::RLA:
         return 4;
     case ExchangeType::SA:
     case ExchangeType::RR:
@@ -55,6 +56,8 @@ std::ostream& operator<<(std::ostream& os, ExchangeType xchg_type)
         return(os << "REQUEST-ACK");
     case ExchangeType::RNA:
         return(os << "REQUEST-ACK (renewal)");
+    case ExchangeType::RLA:
+        return(os << "RELEASE");
     case ExchangeType::SA:
         return(os << "SOLICIT-ADVERTISE");
     case ExchangeType::RR:
@@ -368,7 +371,9 @@ StatsMgr::StatsMgr(CommandOptions& options) :
         if (options.getRenewRate() != 0) {
             addExchangeStats(ExchangeType::RNA);
         }
-
+        if (options.getReleaseRate() != 0) {
+            addExchangeStats(ExchangeType::RLA);
+        }
     } else if (options.getIpVersion() == 6) {
         addExchangeStats(ExchangeType::SA, options.getDropTime()[0]);
         if (options.getExchangeMode() == CommandOptions::DORA_SARR) {
index 1130f244b1a8b3c4c178d017162648bf6d5ea576..39718e9b795b6100f94df2c099af376158a17275 100644 (file)
@@ -33,6 +33,7 @@ enum class ExchangeType {
     DO,  ///< DHCPv4 DISCOVER-OFFER
     RA,  ///< DHCPv4 REQUEST-ACK
     RNA, ///< DHCPv4 REQUEST-ACK (renewal)
+    RLA, ///< DHCPv4 RELEASE
     SA,  ///< DHCPv6 SOLICIT-ADVERTISE
     RR,  ///< DHCPv6 REQUEST-REPLY
     RN,  ///< DHCPv6 RENEW-REPLY
index 8346daa7d8a447e5771e9bc9d169d5e0fd0c39c5..a1f4f7cd556f7b27c28c9038e688badc27e42e33 100644 (file)
@@ -161,15 +161,31 @@ TestControl::byte2Hex(const uint8_t b) {
 }
 
 Pkt4Ptr
-TestControl::createRequestFromAck(const dhcp::Pkt4Ptr& ack) {
+TestControl::createMessageFromAck(const uint16_t msg_type,
+                                  const dhcp::Pkt4Ptr& ack) {
+    // Restrict messages to Release and Renew.
+    if (msg_type != DHCPREQUEST && msg_type != DHCPRELEASE) {
+        isc_throw(isc::BadValue, "invalid message type " << msg_type
+                  << " to be created from Reply, expected DHCPREQUEST or"
+                  " DHCPRELEASE");
+    }
+
+    // Get the string representation of the message - to be used for error
+    // logging purposes.
+    const char* msg_type_str = (msg_type == DHCPREQUEST ? "Request" :
+                                                          "Release");
+
     if (!ack) {
-        isc_throw(isc::BadValue, "Unable to create DHCPREQUEST from a"
-                  " null DHCPACK message");
+        isc_throw(isc::BadValue, "Unable to create "
+                                     << msg_type_str
+                                     << " from a null DHCPACK message");
     } else if (ack->getYiaddr().isV4Zero()) {
-        isc_throw(isc::BadValue, "Unable to create DHCPREQUEST from a"
-                  " DHCPACK message containing yiaddr of 0");
+        isc_throw(isc::BadValue,
+                  "Unable to create "
+                      << msg_type_str
+                      << " from a DHCPACK message containing yiaddr of 0");
     }
-    Pkt4Ptr msg(new Pkt4(DHCPREQUEST, generateTransid()));
+    Pkt4Ptr msg(new Pkt4(msg_type, generateTransid()));
     msg->setCiaddr(ack->getYiaddr());
     msg->setHWAddr(ack->getHWAddr());
     msg->addOption(generateClientId(msg->getHWAddr()));
@@ -185,9 +201,11 @@ TestControl::createMessageFromReply(const uint16_t msg_type,
                   << " to be created from Reply, expected DHCPV6_RENEW or"
                   " DHCPV6_RELEASE");
     }
+
     // Get the string representation of the message - to be used for error
     // logging purposes.
     const char* msg_type_str = (msg_type == DHCPV6_RENEW ? "Renew" : "Release");
+
     // Reply message must be specified.
     if (!reply) {
         isc_throw(isc::BadValue, "Unable to create " << msg_type_str
@@ -535,9 +553,10 @@ TestControl::sendPackets(const uint64_t packets_num,
 }
 
 uint64_t
-TestControl::sendMultipleRequests(const uint64_t msg_num) {
+TestControl::sendMultipleMessages(const uint32_t msg_type,
+                                  const uint64_t msg_num) {
     for (uint64_t i = 0; i < msg_num; ++i) {
-        if (!sendRequestFromAck()) {
+        if (!sendMessageFromAck(msg_type)) {
             return (i);
         }
     }
@@ -786,10 +805,11 @@ TestControl::processReceivedPacket4(const Pkt4Ptr& pkt4) {
             // So, we may need to keep this DHCPACK in the storage if renews.
             // Note that, DHCPACK messages hold the information about
             // leases assigned. We use this information to renew.
-            if (stats_mgr_.hasExchangeStats(ExchangeType::RNA)) {
-                // Renew messages are sent, because StatsMgr has the
-                // specific exchange type specified. Let's append the DHCPACK.
-                // message to a storage
+            if (stats_mgr_.hasExchangeStats(ExchangeType::RNA) ||
+                stats_mgr_.hasExchangeStats(ExchangeType::RLA)) {
+                // Renew or release messages are sent, because StatsMgr has the
+                // specific exchange type specified. Let's append the DHCPACK
+                // message to a storage.
                 ack_storage_.append(pkt4);
             }
         // The DHCPACK message is not a server's response to the DHCPREQUEST
@@ -1247,7 +1267,16 @@ TestControl::sendDiscover4(const std::vector<uint8_t>& template_buf,
 }
 
 bool
-TestControl::sendRequestFromAck() {
+TestControl::sendMessageFromAck(const uint16_t msg_type) {
+    // We only permit Request or Release messages to be sent using this
+    // function.
+    if (msg_type != DHCPREQUEST && msg_type != DHCPRELEASE) {
+        isc_throw(isc::BadValue,
+                  "invalid message type "
+                      << msg_type
+                      << " to be sent, expected DHCPREQUEST or DHCPRELEASE");
+    }
+
     // Get one of the recorded DHCPACK messages.
     Pkt4Ptr ack = ack_storage_.getRandom();
     if (!ack) {
@@ -1255,7 +1284,7 @@ TestControl::sendRequestFromAck() {
     }
 
     // Create message of the specified type.
-    Pkt4Ptr msg = createRequestFromAck(ack);
+    Pkt4Ptr msg = createMessageFromAck(msg_type, ack);
     setDefaults4(msg);
 
     // Override relay address
@@ -1264,10 +1293,15 @@ TestControl::sendRequestFromAck() {
     // Add any extra options that user may have specified.
     addExtraOpts(msg);
 
+    // Pack it.
     msg->pack();
+
     // And send it.
     socket_.send(msg);
-    stats_mgr_.passSentPacket(ExchangeType::RNA, msg);
+    address4Uniqueness(msg, ExchangeType::RLA);
+    stats_mgr_.passSentPacket((msg_type == DHCPREQUEST ? ExchangeType::RNA :
+                                                         ExchangeType::RLA),
+                              msg);
     return (true);
 }
 
@@ -1279,6 +1313,8 @@ TestControl::sendMessageFromReply(const uint16_t msg_type) {
         isc_throw(isc::BadValue, "invalid message type " << msg_type
                   << " to be sent, expected DHCPV6_RENEW or DHCPV6_RELEASE");
     }
+
+    // Get one of the recorded DHCPV6_OFFER messages.
     Pkt6Ptr reply = reply_storage_.getRandom();
     if (!reply) {
         return (false);
@@ -1290,7 +1326,9 @@ TestControl::sendMessageFromReply(const uint16_t msg_type) {
     // Add any extra options that user may have specified.
     addExtraOpts(msg);
 
+    // Pack it.
     msg->pack();
+
     // And send it.
     socket_.send(msg);
     address6Uniqueness(msg, ExchangeType::RL);
index e6a4c24432354770116c0d371347cae2fae6a3d3..292eb36220f0090f1c7cc5b0865de033f8c06f29 100644 (file)
@@ -15,6 +15,7 @@
 #include <perfdhcp/perf_socket.h>
 
 #include <dhcp/iface_mgr.h>
+#include <dhcp/dhcp4.h>
 #include <dhcp/dhcp6.h>
 #include <dhcp/pkt4.h>
 #include <dhcp/pkt6.h>
@@ -268,10 +269,13 @@ public:
 
     /// \brief Send number of DHCPREQUEST (renew) messages to a server.
     ///
+    /// \param msg_type A type of the messages to be sent (DHCPREQUEST or
+    /// DHCPRELEASE).
     /// \param msg_num A number of messages to be sent.
     ///
     /// \return A number of messages actually sent.
-    uint64_t sendMultipleRequests(const uint64_t msg_num);
+    uint64_t sendMultipleMessages(const uint32_t msg_type,
+                                  const uint64_t msg_num);
 
     /// \brief Send number of DHCPv6 Renew or Release messages to the server.
     ///
@@ -352,7 +356,8 @@ protected:
     /// create a new message.
     ///
     /// \return Pointer to the created message.
-    dhcp::Pkt4Ptr createRequestFromAck(const dhcp::Pkt4Ptr& ack);
+    dhcp::Pkt4Ptr createMessageFromAck(const uint16_t msg_type,
+                                       const dhcp::Pkt4Ptr& ack);
 
     /// \brief Creates DHCPv6 message from the Reply packet.
     ///
@@ -630,6 +635,7 @@ protected:
                 }
                 break;
             }
+            case ExchangeType::RLA:
             case ExchangeType::RL: {
                 removeUniqueAddr(current);
                 break;
@@ -794,8 +800,11 @@ protected:
 
     /// \brief Send DHCPv4 renew (DHCPREQUEST).
     ///
+    /// \param msg_type A type of the message to be sent (DHCPREQUEST or
+    /// DHCPRELEASE).
+    ///
     /// \return true if the message has been sent, false otherwise.
-    bool sendRequestFromAck();
+    bool sendMessageFromAck(const uint16_t msg_type);
 
     /// \brief Send DHCPv6 Renew or Release message.
     ///