From: Andrei Pavel Date: Tue, 12 Mar 2024 11:22:08 +0000 (+0200) Subject: [#3262] check parking limit on subnet select X-Git-Tag: Kea-2.5.7~74 X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=8491e56aa843499e438ad4b768a90f264ef125bc;p=thirdparty%2Fkea.git [#3262] check parking limit on subnet select --- diff --git a/src/bin/dhcp4/dhcp4_messages.cc b/src/bin/dhcp4/dhcp4_messages.cc index b31f22c7d2..9a1069c0b3 100644 --- a/src/bin/dhcp4/dhcp4_messages.cc +++ b/src/bin/dhcp4/dhcp4_messages.cc @@ -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", diff --git a/src/bin/dhcp4/dhcp4_messages.h b/src/bin/dhcp4/dhcp4_messages.h index 8427698ed1..79c5631acd 100644 --- a/src/bin/dhcp4/dhcp4_messages.h +++ b/src/bin/dhcp4/dhcp4_messages.h @@ -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; diff --git a/src/bin/dhcp4/dhcp4_messages.mes b/src/bin/dhcp4/dhcp4_messages.mes index a439bbdb32..57f75d1d01 100644 --- a/src/bin/dhcp4/dhcp4_messages.mes +++ b/src/bin/dhcp4/dhcp4_messages.mes @@ -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 diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 4f4279a9c1..7c75edde28 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -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(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(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 +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; diff --git a/src/bin/dhcp4/dhcp4_srv.h b/src/bin/dhcp4/dhcp4_srv.h index 8fc54d6436..85f9bce975 100644 --- a/src/bin/dhcp4/dhcp4_srv.h +++ b/src/bin/dhcp4/dhcp4_srv.h @@ -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 parkingLimitExceeded(std::string const& hook_label); + protected: /// UDP port number on which server listens. diff --git a/src/bin/dhcp6/dhcp6_messages.cc b/src/bin/dhcp6/dhcp6_messages.cc index 4df743c68f..d5ab190109 100644 --- a/src/bin/dhcp6/dhcp6_messages.cc +++ b/src/bin/dhcp6/dhcp6_messages.cc @@ -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", diff --git a/src/bin/dhcp6/dhcp6_messages.h b/src/bin/dhcp6/dhcp6_messages.h index 5df401a99e..91555d2d11 100644 --- a/src/bin/dhcp6/dhcp6_messages.h +++ b/src/bin/dhcp6/dhcp6_messages.h @@ -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; diff --git a/src/bin/dhcp6/dhcp6_messages.mes b/src/bin/dhcp6/dhcp6_messages.mes index 131d08de18..25fd6bd78b 100644 --- a/src/bin/dhcp6/dhcp6_messages.mes +++ b/src/bin/dhcp6/dhcp6_messages.mes @@ -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 diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 574e6b0442..1e9468e46b 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -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 +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(); diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h index 7a9331bb93..319d5ffe38 100644 --- a/src/bin/dhcp6/dhcp6_srv.h +++ b/src/bin/dhcp6/dhcp6_srv.h @@ -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 parkingLimitExceeded(std::string const& hook_label); + protected: /// UDP port number on which server listens. uint16_t server_port_;