]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#3262] check parking limit on subnet select
authorAndrei Pavel <andrei@isc.org>
Tue, 12 Mar 2024 11:22:08 +0000 (13:22 +0200)
committerAndrei Pavel <andrei@isc.org>
Mon, 18 Mar 2024 09:33:11 +0000 (11:33 +0200)
src/bin/dhcp4/dhcp4_messages.cc
src/bin/dhcp4/dhcp4_messages.h
src/bin/dhcp4/dhcp4_messages.mes
src/bin/dhcp4/dhcp4_srv.cc
src/bin/dhcp4/dhcp4_srv.h
src/bin/dhcp6/dhcp6_messages.cc
src/bin/dhcp6/dhcp6_messages.h
src/bin/dhcp6/dhcp6_messages.mes
src/bin/dhcp6/dhcp6_srv.cc
src/bin/dhcp6/dhcp6_srv.h

index b31f22c7d211988a6312aaa629e9131a9abe0786..9a1069c0b38f6d6c9d32687b3ef12db11852168d 100644 (file)
@@ -94,8 +94,10 @@ extern const isc::log::MessageID DHCP4_HOOK_LEASES4_COMMITTED_PARKING_LOT_FULL =
 extern const isc::log::MessageID DHCP4_HOOK_PACKET_RCVD_SKIP = "DHCP4_HOOK_PACKET_RCVD_SKIP";
 extern const isc::log::MessageID DHCP4_HOOK_PACKET_SEND_DROP = "DHCP4_HOOK_PACKET_SEND_DROP";
 extern const isc::log::MessageID DHCP4_HOOK_PACKET_SEND_SKIP = "DHCP4_HOOK_PACKET_SEND_SKIP";
+extern const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_4O6_PARKING_LOT_FULL = "DHCP4_HOOK_SUBNET4_SELECT_4O6_PARKING_LOT_FULL";
 extern const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_DROP = "DHCP4_HOOK_SUBNET4_SELECT_DROP";
 extern const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_PARK = "DHCP4_HOOK_SUBNET4_SELECT_PARK";
+extern const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_PARKING_LOT_FULL = "DHCP4_HOOK_SUBNET4_SELECT_PARKING_LOT_FULL";
 extern const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_SKIP = "DHCP4_HOOK_SUBNET4_SELECT_SKIP";
 extern const isc::log::MessageID DHCP4_INFORM_DIRECT_REPLY = "DHCP4_INFORM_DIRECT_REPLY";
 extern const isc::log::MessageID DHCP4_INIT_FAIL = "DHCP4_INIT_FAIL";
@@ -279,8 +281,10 @@ const char* values[] = {
     "DHCP4_HOOK_PACKET_RCVD_SKIP", "%1: packet is dropped, because a callout set the next step to SKIP",
     "DHCP4_HOOK_PACKET_SEND_DROP", "%1: prepared DHCPv4 response was not sent because a callout set the next ste to DROP",
     "DHCP4_HOOK_PACKET_SEND_SKIP", "%1: prepared response is not sent, because a callout set the next stp to SKIP",
+    "DHCP4_HOOK_SUBNET4_SELECT_4O6_PARKING_LOT_FULL", "The parked-packet-limit %1, has been reached, dropping query: %2",
     "DHCP4_HOOK_SUBNET4_SELECT_DROP", "%1: packet was dropped, because a callout set the next step to 'drop'",
     "DHCP4_HOOK_SUBNET4_SELECT_PARK", "%1: packet was parked",
+    "DHCP4_HOOK_SUBNET4_SELECT_PARKING_LOT_FULL", "The parked-packet-limit %1, has been reached, dropping query: %2",
     "DHCP4_HOOK_SUBNET4_SELECT_SKIP", "%1: no subnet was selected, because a callout set the next skip flag",
     "DHCP4_INFORM_DIRECT_REPLY", "%1: DHCPACK in reply to the DHCPINFORM will be sent directly to %2 over %3",
     "DHCP4_INIT_FAIL", "failed to initialize Kea server: %1",
index 8427698ed19b8706b049ef2f068023988cd3edc7..79c5631acda4f50b642b91b4de6193b8fece4a66 100644 (file)
@@ -95,8 +95,10 @@ extern const isc::log::MessageID DHCP4_HOOK_LEASES4_COMMITTED_PARKING_LOT_FULL;
 extern const isc::log::MessageID DHCP4_HOOK_PACKET_RCVD_SKIP;
 extern const isc::log::MessageID DHCP4_HOOK_PACKET_SEND_DROP;
 extern const isc::log::MessageID DHCP4_HOOK_PACKET_SEND_SKIP;
+extern const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_4O6_PARKING_LOT_FULL;
 extern const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_DROP;
 extern const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_PARK;
+extern const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_PARKING_LOT_FULL;
 extern const isc::log::MessageID DHCP4_HOOK_SUBNET4_SELECT_SKIP;
 extern const isc::log::MessageID DHCP4_INFORM_DIRECT_REPLY;
 extern const isc::log::MessageID DHCP4_INIT_FAIL;
index a439bbdb32ed31d82d32182388c2917ab303fdf5..57f75d1d01eed93bdc164e8d3c7d4c48aea1e19c 100644 (file)
@@ -468,7 +468,7 @@ hook point sets the next step to PARK.
 
 % DHCP4_HOOK_LEASE4_OFFER_PARKING_LOT_FULL The parked-packet-limit %1, has been reached, dropping query: %2
 This debug message occurs when the parking lot used to hold client queries
-while hook library work for them completes has reached or exceeded the
+while the hook library work for them completes has reached or exceeded the
 limit set by the parked-packet-limit global parameter. This can occur when
 kea-dhcp4 is using hook libraries (e.g. ping-check) that implement the
 "lease4_offer" callout and client queries are arriving faster than
@@ -489,7 +489,7 @@ hook point sets the next step to PARK.
 
 % DHCP4_HOOK_LEASES4_COMMITTED_PARKING_LOT_FULL The parked-packet-limit %1, has been reached, dropping query: %2
 This debug message occurs when the parking lot used to hold client queries
-while hook library work for them completes has reached or exceeded the
+while the hook library work for them completes has reached or exceeded the
 limit set by the parked-packet-limit global parameter. This can occur when
 kea-dhcp4 is using hook libraries (e.g. HA) that implement the
 "leases4-committed" callout and client queries are arriving faster than
@@ -516,6 +516,14 @@ setting instructs the server to drop the packet. This means that
 the client will not get any response, even though the server processed
 client's request and acted on it (e.g. possibly allocated a lease).
 
+% DHCP4_HOOK_SUBNET4_SELECT_4O6_PARKING_LOT_FULL The parked-packet-limit %1, has been reached, dropping query: %2
+This debug message occurs when the parking lot used to hold client queries
+while the hook library work for them completes has reached or exceeded the
+limit set by the parked-packet-limit global parameter. This can occur when
+kea-dhcp4 is using hook libraries (e.g. radius) that implement the
+"subnet4_select" callout and DHCP4O6 client queries are arriving faster than
+those callouts can fulfill them.
+
 % DHCP4_HOOK_SUBNET4_SELECT_DROP %1: packet was dropped, because a callout set the next step to 'drop'
 This debug message is printed when a callout installed on the
 subnet4_select hook point sets the next step to 'drop' value. For this particular hook
@@ -528,6 +536,14 @@ This debug message is printed when a callout installed on the
 subnet4_select hook point set the park flag. The argument holds the
 client and transaction identification information.
 
+% DHCP4_HOOK_SUBNET4_SELECT_PARKING_LOT_FULL The parked-packet-limit %1, has been reached, dropping query: %2
+This debug message occurs when the parking lot used to hold client queries
+while the hook library work for them completes has reached or exceeded the
+limit set by the parked-packet-limit global parameter. This can occur when
+kea-dhcp4 is using hook libraries (e.g. radius) that implement the
+"subnet4_select" callout and client queries are arriving faster than
+those callouts can fulfill them.
+
 % DHCP4_HOOK_SUBNET4_SELECT_SKIP %1: no subnet was selected, because a callout set the next skip flag
 This debug message is printed when a callout installed on the
 subnet4_select hook point sets the next step to SKIP value. For this particular hook
index 4f4279a9c15da6b176bc0bea85a8c5ed372ebf64..7c75edde28d07403cdc25b48b5e7addea91db63f 100644 (file)
@@ -77,6 +77,7 @@
 using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::cryptolink;
+using namespace isc::data;
 using namespace isc::dhcp;
 using namespace isc::dhcp_ddns;
 using namespace isc::hooks;
@@ -757,6 +758,18 @@ Dhcpv4Srv::selectSubnet(const Pkt4Ptr& query, bool& drop,
                                     cfgmgr.getCurrentCfg()->
                                     getCfgSubnets4()->getAll());
 
+        auto const tpl(parkingLimitExceeded("subnet4_select"));
+        bool const exceeded(get<0>(tpl));
+        if (exceeded) {
+            uint32_t const limit(get<1>(tpl));
+            // We can't park it so we're going to throw it on the floor.
+            LOG_DEBUG(packet4_logger, DBGLVL_PKT_HANDLING,
+                      DHCP4_HOOK_SUBNET4_SELECT_PARKING_LOT_FULL)
+                .arg(limit)
+                .arg(query->getLabel());
+            return (Subnet4Ptr());
+        }
+
         // We proactively park the packet.
         HooksManager::park(
             "subnet4_select", query, [this, query, allow_answer_park, callout_handle_state]() {
@@ -913,6 +926,18 @@ Dhcpv4Srv::selectSubnet4o6(const Pkt4Ptr& query, bool& drop,
                                     cfgmgr.getCurrentCfg()->
                                     getCfgSubnets4()->getAll());
 
+        auto const tpl(parkingLimitExceeded("subnet4_select"));
+        bool const exceeded(get<0>(tpl));
+        if (exceeded) {
+            uint32_t const limit(get<1>(tpl));
+            // We can't park it so we're going to throw it on the floor.
+            LOG_DEBUG(packet4_logger, DBGLVL_PKT_HANDLING,
+                      DHCP4_HOOK_SUBNET4_SELECT_4O6_PARKING_LOT_FULL)
+                .arg(limit)
+                .arg(query->getLabel());
+            return (Subnet4Ptr());
+        }
+
         // We proactively park the packet.
         HooksManager::park(
             "subnet4_select", query, [this, query, allow_answer_park, callout_handle_state]() {
@@ -1653,27 +1678,17 @@ Dhcpv4Srv::processLocalizedQuery4(AllocEngine::ClientContext4Ptr& ctx,
             }
 
             if (allow_answer_park) {
-                // Get the parking limit. Parsing should ensure the value is present.
-                uint32_t parked_packet_limit = 0;
-                data::ConstElementPtr ppl = CfgMgr::instance().getCurrentCfg()->
-                    getConfiguredGlobal(CfgGlobals::PARKED_PACKET_LIMIT);
-                if (ppl) {
-                    parked_packet_limit = ppl->intValue();
-                }
-
-                if (parked_packet_limit) {
-                    auto const& parking_lot =
-                        ServerHooks::getServerHooks().getParkingLotPtr(hook_label);
-
-                    if (parking_lot && (parking_lot->size() >= parked_packet_limit)) {
-                        // We can't park it so we're going to throw it on the floor.
-                        LOG_DEBUG(packet4_logger, DBGLVL_PKT_HANDLING, parking_lot_full_msg)
-                            .arg(parked_packet_limit)
-                            .arg(query->getLabel());
-                        isc::stats::StatsMgr::instance().addValue("pkt4-receive-drop",
-                                                                  static_cast<int64_t>(1));
-                        return (Pkt4Ptr());
-                    }
+                auto const tpl(parkingLimitExceeded(hook_label));
+                bool const exceeded(get<0>(tpl));
+                if (exceeded) {
+                    uint32_t const limit(get<1>(tpl));
+                    // We can't park it so we're going to throw it on the floor.
+                    LOG_DEBUG(packet4_logger, DBGLVL_PKT_HANDLING, parking_lot_full_msg)
+                        .arg(limit)
+                        .arg(query->getLabel());
+                    isc::stats::StatsMgr::instance().addValue("pkt4-receive-drop",
+                                                                static_cast<int64_t>(1));
+                    return (Pkt4Ptr());
                 }
 
                 // We proactively park the packet. We'll unpark it without invoking
@@ -3635,6 +3650,27 @@ Dhcpv4Srv::getNetmaskOption(const Subnet4Ptr& subnet) {
     return (opt);
 }
 
+tuple<bool, uint32_t>
+Dhcpv4Srv::parkingLimitExceeded(string const& hook_label) {
+    // Get the parking limit. Parsing should ensure the value is present.
+    uint32_t parked_packet_limit(0);
+    ConstElementPtr const& ppl(
+        CfgMgr::instance().getCurrentCfg()->getConfiguredGlobal(CfgGlobals::PARKED_PACKET_LIMIT));
+    if (ppl) {
+        parked_packet_limit = ppl->intValue();
+    }
+
+    if (parked_packet_limit) {
+        ParkingLotPtr const& parking_lot(
+            ServerHooks::getServerHooks().getParkingLotPtr(hook_label));
+
+        if (parking_lot && parked_packet_limit <= parking_lot->size()) {
+            return make_tuple(true, parked_packet_limit);
+        }
+    }
+    return make_tuple(false, parked_packet_limit);
+}
+
 Pkt4Ptr
 Dhcpv4Srv::processDiscover(Pkt4Ptr& discover, AllocEngine::ClientContext4Ptr& context) {
     bool drop = false;
index 8fc54d64364c4f2a832ef9812017e924c36b11ab..85f9bce975ae58f2c6e4c108deeb9ef4f87f303d 100644 (file)
@@ -1181,7 +1181,6 @@ protected:
 
 private:
 
-    /// @public
     /// @brief Assign class using vendor-class-identifier option
     ///
     /// @note This is the first part of @ref classifyPacket
@@ -1189,13 +1188,20 @@ private:
     /// @param pkt packet to be classified
     void classifyByVendor(const Pkt4Ptr& pkt);
 
-    /// @private
     /// @brief Constructs netmask option based on subnet4
     /// @param subnet subnet for which the netmask will be calculated
     ///
     /// @return Option that contains netmask information
     static OptionPtr getNetmaskOption(const Subnet4Ptr& subnet);
 
+    /// @brief Check if the parking limit has been exceeded for given hook label.
+    ///
+    /// @brief hook_label Hook point name.
+    ///
+    /// @return tuple with boolean value concluding whether the limit has been
+    /// exceeded, and the integer limit as a second value.
+    static std::tuple<bool, uint32_t> parkingLimitExceeded(std::string const& hook_label);
+
 protected:
 
     /// UDP port number on which server listens.
index 4df743c68fa26383b5a1ba80f1d070e96e21938e..d5ab19010994d6a5c63ed3fc51688f45d20fa6db 100644 (file)
@@ -7,6 +7,7 @@
 namespace isc {
 namespace dhcp {
 
+extern const isc::log::MessageID DHCP4_HOOK_SUBNET6_SELECT_PARKING_LOT_FULL = "DHCP4_HOOK_SUBNET6_SELECT_PARKING_LOT_FULL";
 extern const isc::log::MessageID DHCP6_ACTIVATE_INTERFACE = "DHCP6_ACTIVATE_INTERFACE";
 extern const isc::log::MessageID DHCP6_ADD_GLOBAL_STATUS_CODE = "DHCP6_ADD_GLOBAL_STATUS_CODE";
 extern const isc::log::MessageID DHCP6_ADD_STATUS_CODE_FOR_IA = "DHCP6_ADD_STATUS_CODE_FOR_IA";
@@ -182,6 +183,7 @@ extern const isc::log::MessageID DHCP6_USING_SERVERID = "DHCP6_USING_SERVERID";
 namespace {
 
 const char* values[] = {
+    "DHCP4_HOOK_SUBNET6_SELECT_PARKING_LOT_FULL", "The parked-packet-limit %1, has been reached, dropping query: %2",
     "DHCP6_ACTIVATE_INTERFACE", "activating interface %1",
     "DHCP6_ADD_GLOBAL_STATUS_CODE", "%1: adding Status Code to DHCPv6 packet: %2",
     "DHCP6_ADD_STATUS_CODE_FOR_IA", "%1: adding Status Code to IA with iaid=%2: %3",
index 5df401a99e7bb7889b477791cbb34309438ba58c..91555d2d11622e7a79362fe2676f98d1a69a77a2 100644 (file)
@@ -8,6 +8,7 @@
 namespace isc {
 namespace dhcp {
 
+extern const isc::log::MessageID DHCP4_HOOK_SUBNET6_SELECT_PARKING_LOT_FULL;
 extern const isc::log::MessageID DHCP6_ACTIVATE_INTERFACE;
 extern const isc::log::MessageID DHCP6_ADD_GLOBAL_STATUS_CODE;
 extern const isc::log::MessageID DHCP6_ADD_STATUS_CODE_FOR_IA;
index 131d08de18cd84fef07c088db10ae17d612c5238..25fd6bd78b6d59ccf575ece804057cffcabfefaa 100644 (file)
@@ -437,7 +437,7 @@ hook point sets the next step to PARK.
 
 % DHCP6_HOOK_LEASES6_PARKING_LOT_FULL The parked-packet-limit %1, has been reached, dropping query: %2
 This debug message occurs when the parking lot used to hold client queries
-while hook library work for them completes has reached or exceeded the
+while the hook library work for them completes has reached or exceeded the
 limit set by the parked-packet-limit global parameter. This can occur when
 kea-dhcp6 is using hook libraries (e.g. HA) that implement the
 "leases6-committed" callout and client queries are arriving faster than
@@ -477,6 +477,14 @@ This debug message is printed when a callout installed on the
 subnet6_select hook point set the park flag. The argument holds the
 client and transaction identification information.
 
+% DHCP4_HOOK_SUBNET6_SELECT_PARKING_LOT_FULL The parked-packet-limit %1, has been reached, dropping query: %2
+This debug message occurs when the parking lot used to hold client queries
+while the hook library work for them completes has reached or exceeded the
+limit set by the parked-packet-limit global parameter. This can occur when
+kea-dhcp4 is using hook libraries (e.g. radius) that implement the
+"subnet6_select" callout and client queries are arriving faster than
+those callouts can fulfill them.
+
 % DHCP6_HOOK_SUBNET6_SELECT_SKIP %1: no subnet was selected because a callout set the next step to SKIP
 This debug message is printed when a callout installed on the
 subnet6_select hook point set the next step to SKIP value. For this particular hook
index 574e6b04423af27ccfec88f6b6764d05fd9e08ac..1e9468e46b156050e5a29abcf27e8ee79de3a455 100644 (file)
@@ -82,6 +82,7 @@
 using namespace isc;
 using namespace isc::asiolink;
 using namespace isc::cryptolink;
+using namespace isc::data;
 using namespace isc::dhcp;
 using namespace isc::dhcp_ddns;
 using namespace isc::hooks;
@@ -2023,6 +2024,18 @@ Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question, bool& drop) {
                                     CfgMgr::instance().getCurrentCfg()->
                                     getCfgSubnets6()->getAll());
 
+        auto const tpl(parkingLimitExceeded("subnet6_select"));
+        bool const exceeded(get<0>(tpl));
+        if (exceeded) {
+            uint32_t const limit(get<1>(tpl));
+            // We can't park it so we're going to throw it on the floor.
+            LOG_DEBUG(packet6_logger, DBGLVL_PKT_HANDLING,
+                      DHCP4_HOOK_SUBNET6_SELECT_PARKING_LOT_FULL)
+                .arg(limit)
+                .arg(question->getLabel());
+            return (Subnet6Ptr());
+        }
+
         // We proactively park the packet.
         // Not MT compatible because the unparking callback can be called
         // before the current thread exists from this block.
@@ -4803,6 +4816,28 @@ Dhcpv6Srv::requestedInORO(const Pkt6Ptr& query, const uint16_t code) const {
     return (false);
 }
 
+tuple<bool, uint32_t>
+Dhcpv6Srv::parkingLimitExceeded(string const& hook_label) {
+    // Get the parking limit. Parsing should ensure the value is present.
+    uint32_t parked_packet_limit(0);
+    ConstElementPtr const& ppl(
+        CfgMgr::instance().getCurrentCfg()->getConfiguredGlobal(CfgGlobals::PARKED_PACKET_LIMIT));
+    if (ppl) {
+        parked_packet_limit = ppl->intValue();
+    }
+
+    if (parked_packet_limit) {
+        ParkingLotPtr const& parking_lot(
+            ServerHooks::getServerHooks().getParkingLotPtr(hook_label));
+
+        if (parking_lot && parked_packet_limit <= parking_lot->size()) {
+            return make_tuple(true, parked_packet_limit);
+        }
+    }
+    return make_tuple(false, parked_packet_limit);
+}
+
+
 void Dhcpv6Srv::discardPackets() {
     // Dump all of our current packets, anything that is mid-stream
     HooksManager::clearParkingLots();
index 7a9331bb931f39143508c47d560423e4c7223cc5..319d5ffe3805d1a490cdfa8ea251884af2fce9ae 100644 (file)
@@ -1155,6 +1155,14 @@ private:
     /// @return true if option has been requested in the ORO.
     bool requestedInORO(const Pkt6Ptr& query, const uint16_t code) const;
 
+    /// @brief Check if the parking limit has been exceeded for given hook label.
+    ///
+    /// @brief hook_label Hook point name.
+    ///
+    /// @return tuple with boolean value concluding whether the limit has been
+    /// exceeded, and the integer limit as a second value.
+    static std::tuple<bool, uint32_t> parkingLimitExceeded(std::string const& hook_label);
+
 protected:
     /// UDP port number on which server listens.
     uint16_t server_port_;