7#ifndef ISC_LIMITS_RATE_LIMIT_MANAGER_H
8#define ISC_LIMITS_RATE_LIMIT_MANAGER_H
26#include <boost/circular_buffer.hpp>
29#include <unordered_map>
36using TimePoint = std::chrono::time_point<std::chrono::system_clock>;
93 template <isc::util::DhcpSpace D>
102 handle.
getArgument(
"audit_entries", audit_entries);
103 if (!audit_entries) {
108 auto const& client_class_range(object_type_index.equal_range(
110 auto const& subnet_range(object_type_index.equal_range(
114 if (std::distance(client_class_range.first, client_class_range.second) ||
115 std::distance(subnet_range.first, subnet_range.second)) {
130 template <isc::util::DhcpSpace D>
140 recountClassLeases<D>();
145 ->getLeaseDbAccessString());
146 if ((lease_db_access_string.find(
"retry-on-startup=true") != std::string::npos) &&
147 ((lease_db_access_string.find(
"type=mysql") != std::string::npos) ||
148 (lease_db_access_string.find(
"type=postgresql") != std::string::npos))) {
169 template <isc::util::DhcpSpace D>
183 auto const& classes(packet->getClasses());
188 auto const& relations = packet->getSubClassesRelations();
191 TimePoint const now(std::chrono::system_clock::now());
194 std::vector<isc::dhcp::ClientClass> common_client_classes;
203 for (
auto const& c : relations) {
209 auto const &limit_cfg = rate_limit_configuration_.parseUserContext(class_def->getContext());
216 RateLimit const& limit(limit_cfg->stringValue());
219 TimeSeries& time_series(clocked_in_times_by_class_[c.class_]);
224 while (!time_series.empty()) {
225 if (time_series.back() + limit.
time_unit_ < now) {
226 time_series.pop_back();
241 .arg(classes.toText())
253 common_client_classes.push_back(c.class_);
259 stats_mgr.
addValue(
"pkt4-limit-exceeded",
260 static_cast<int64_t
>(1));
261 stats_mgr.
addValue(
"pkt4-receive-drop",
262 static_cast<int64_t
>(1));
264 stats_mgr.
addValue(
"pkt6-limit-exceeded",
265 static_cast<int64_t
>(1));
266 stats_mgr.
addValue(
"pkt6-receive-drop",
267 static_cast<int64_t
>(1));
271 for (
auto const& c : common_client_classes) {
272 TimeSeries& time_series(clocked_in_times_by_class_.at(c));
273 time_series.push_front(now);
277 if (!common_client_classes.empty()) {
280 .arg(classes.toText());
299 template <isc::util::DhcpSpace D>
318 auto const& limit_cfg = subnetRateLimit<D>(subnet_id);
321 limit =
RateLimit(limit_cfg->stringValue());
334 if (!time_series_ref) {
335 time_series_ref = std::make_shared<ProtectedTimeSeries>();
337 time_series = time_series_ref;
341 TimePoint const now(std::chrono::system_clock::now());
349 while (!time_series->time_points_.empty()) {
350 if (time_series->time_points_.back() + limit.
time_unit_ < now) {
351 time_series->time_points_.pop_back();
362 time_series->time_points_.push_front(now);
374 stats_mgr.
addValue(
"pkt4-limit-exceeded",
375 static_cast<int64_t
>(1));
376 stats_mgr.
addValue(
"pkt4-receive-drop",
377 static_cast<int64_t
>(1));
379 stats_mgr.
addValue(
"pkt6-limit-exceeded",
380 static_cast<int64_t
>(1));
381 stats_mgr.
addValue(
"pkt6-receive-drop",
382 static_cast<int64_t
>(1));
411 template <isc::util::DhcpSpace D>
433 auto const& classes(packet->getClasses());
436 addClientClassesToLeaseContext(classes, lease);
446 auto const& relations(packet->getSubClassesRelations());
450 isc::data::ElementPtr client_class_limits = clientClassLimitsToElement<D>(relations, lease->getType());
456 if (!client_class_limits->empty()) {
457 limits->set(
"client-classes", client_class_limits);
459 if (!subnet_limit->empty()) {
460 limits->set(
"subnet", subnet_limit);
468 ISC->set(
"limits",
limits);
470 context->set(
"ISC", ISC);
473 std::string
const limit_exceeded_text(checkLeaseLimits<D>(context));
474 if (limit_exceeded_text.empty()) {
482 .arg(limit_exceeded_text);
507 template <isc::util::DhcpSpace D>
521 template <isc::util::DhcpSpace D>
532 template <isc::util::DhcpSpace D>
546 template <isc::util::DhcpSpace D>
552 template <isc::util::DhcpSpace D>
553 void recountClassLeases()
const;
557 std::unordered_map<isc::dhcp::ClientClass, TimeSeries> clocked_in_times_by_class_;
561 std::unordered_map<isc::dhcp::SubnetID, ProtectedTimeSeriesPtr> clocked_in_times_by_subnet_id_;
Defines elements for storing the names of client classes.
A generic exception that is thrown when an unexpected error condition occurs.
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
static CfgMgr & instance()
returns a single instance of Configuration Manager
SrvConfigPtr getCurrentCfg()
Returns a pointer to the current configuration.
Container for storing client class names.
static bool haveInstance()
Indicates if the lease manager has been instantiated.
Per-packet callout handle.
CalloutNextStep
Specifies allowed next steps.
@ NEXT_STEP_DROP
drop the packet
@ NEXT_STEP_SKIP
skip the next processing step
CalloutNextStep getStatus() const
Returns the next processing step.
void setStatus(const CalloutNextStep next)
Sets the next processing step.
void getArgument(const std::string &name, T &value) const
Get argument.
Statistics Manager class.
static StatsMgr & instance()
Statistics Manager accessor method.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
void addValue(const std::string &name, const int64_t value)
Records incremental integer observation.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
boost::shared_ptr< const Element > ConstElementPtr
boost::shared_ptr< Element > ElementPtr
boost::shared_ptr< AuditEntryCollection > AuditEntryCollectionPtr
boost::shared_ptr< PktT< D > > PktTPtr
boost::shared_ptr< LeaseT< D > > LeaseTPtr
boost::shared_ptr< SrvConfig > SrvConfigPtr
Non-const pointer to the SrvConfig.
boost::shared_ptr< const SubnetT< D > > ConstSubnetTPtr
boost::multi_index_container< SubClassRelation, boost::multi_index::indexed_by< boost::multi_index::sequenced< boost::multi_index::tag< TemplateClassSequenceTag > >, boost::multi_index::hashed_unique< boost::multi_index::tag< TemplateClassNameTag >, boost::multi_index::member< SubClassRelation, ClientClass, &SubClassRelation::class_def_ > > > > SubClassRelationContainer
the subclass multi-index.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
boost::shared_ptr< Lease > LeasePtr
Pointer to the lease object.
std::shared_ptr< ProtectedTimeSeries > ProtectedTimeSeriesPtr
Defines a smart pointer to a ProtectedTimeSeries.
const isc::log::MessageID LIMITS_CONFIGURATION_LEASE_BACKEND_NOT_AVAILABLE
std::chrono::time_point< std::chrono::system_clock > TimePoint
a point in time
const isc::log::MessageID LIMITS_PACKET_WITH_SUBNET_ID_RATE_LIMIT_HONORED
const isc::log::MessageID LIMITS_LEASE_LIMIT_EXCEEDED
const isc::log::MessageID LIMITS_PACKET_WITH_SUBNET_ID_RATE_LIMIT_DROPPED
const isc::log::MessageID LIMITS_LEASE_WITHIN_LIMITS
boost::circular_buffer< TimePoint > TimeSeries
Holds a number of time points, used in limiting by a single criterion.
const isc::log::MessageID LIMITS_PACKET_WITH_CLIENT_CLASSES_RATE_LIMIT_DROPPED
const isc::log::MessageID LIMITS_PACKET_WIIH_SUBNET_ID_RATE_NO_SUBNET
const isc::log::MessageID LIMITS_CONFIGURATION_LEASE_BACKEND_SHOULD_HAVE_BEEN_AVAILABLE
const isc::log::MessageID LIMITS_PACKET_WITH_CLIENT_CLASSES_RATE_LIMIT_HONORED
isc::log::Logger limits_logger("limits-hooks")
const int DBGLVL_TRACE_BASIC
Trace basic operations.
const int DBGLVL_TRACE_DETAIL_DATA
Trace data associated with detailed operations.
std::string formatDhcpSpace(char const *const format_string)
Replaces all occurrences of {} with 4 or 6 based on the templated DHCP space.
Defines the logger used by the top-level component of kea-lfc.
Tag used to access index by object type.
Type
Type of lease or pool.
the configuration manager for address limiting
Provides the capability to limit the number of leases or the response rate.
int cb_updated(isc::hooks::CalloutHandle &handle)
cbX_updated hook point
int dhcp_srv_configured(isc::hooks::CalloutHandle &handle)
dhcpX_srv_configured hook point
int subnet_select(isc::hooks::CalloutHandle &handle)
subnetX_select hook point
int pkt_receive(isc::hooks::CalloutHandle &handle)
pktX_receive hook point
void parse(isc::dhcp::SrvConfigPtr const &config)
Fetches limits from the given Kea configuration.
int lease_callout(isc::hooks::CalloutHandle &handle, bool lease_update=false)
leaseX_select hook point
void clear()
Clears the time series circular buffers in order to start over rate limiting.
void initialize(isc::dhcp::SrvConfigPtr const &config)
Reinitialize data structures required for limiting.
static LimitManager & instance()
singleton access function
the configuration manager for prefix limiting
Holds a number of time points, used in limiting by a single criterion, and a mutex to protect concurr...
std::mutex mutex_
Protects against races on the time points which can be edited at each hook callout.
TimeSeries time_points_
Holds the actual time points.
the configuration manager for rate limiting
a single rate-limiting entry configured as "rate-limit": "<n> packet[s] per <time-unit>"
std::string text_
a string representation of the rate limit as specified in the configuration used for logging purposes
std::chrono::seconds time_unit_
Seconds of one time unit's worth.
uint32_t allowed_packets_
the configured limit
RAII lock object to protect the code in the same scope with a mutex.