7#ifndef ISC_LIMITS_RATE_LIMIT_MANAGER_H
8#define ISC_LIMITS_RATE_LIMIT_MANAGER_H
25#include <boost/circular_buffer.hpp>
28#include <unordered_map>
35using TimePoint = std::chrono::time_point<std::chrono::system_clock>;
92 template <isc::util::DhcpSpace D>
101 handle.
getArgument(
"audit_entries", audit_entries);
102 if (!audit_entries) {
107 auto const& client_class_range(object_type_index.equal_range(
109 auto const& subnet_range(object_type_index.equal_range(
113 if (std::distance(client_class_range.first, client_class_range.second) ||
114 std::distance(subnet_range.first, subnet_range.second)) {
129 template <isc::util::DhcpSpace D>
140 const std::string
error(
"The lease database you have configured "
141 "does not support JSON operations which are required for lease "
149 recountClassLeases<D>();
154 ->getLeaseDbAccessString());
155 if (lease_db_access_string.find(
"retry-on-startup=true") &&
156 (lease_db_access_string.find(
"type=mysql") ||
157 lease_db_access_string.find(
"type=postgresql"))) {
178 template <isc::util::DhcpSpace D>
192 auto const& classes(packet->getClasses());
197 auto const& relations = packet->getSubClassesRelations();
200 TimePoint const now(std::chrono::system_clock::now());
203 std::vector<isc::dhcp::ClientClass> common_client_classes;
212 for (
auto const& c : relations) {
218 auto const &limit_cfg = rate_limit_configuration_.parseUserContext(class_def->getContext());
225 RateLimit const& limit(limit_cfg->stringValue());
228 TimeSeries& time_series(clocked_in_times_by_class_[c.class_]);
233 while (!time_series.empty()) {
234 if (time_series.back() + limit.
time_unit_ < now) {
235 time_series.pop_back();
250 .arg(classes.toText())
262 common_client_classes.push_back(c.class_);
267 for (
auto const& c : common_client_classes) {
268 TimeSeries& time_series(clocked_in_times_by_class_.at(c));
269 time_series.push_front(now);
273 if (!common_client_classes.empty()) {
276 .arg(classes.toText());
295 template <isc::util::DhcpSpace D>
314 auto const& limit_cfg = subnetRateLimit<D>(subnet_id);
317 limit =
RateLimit(limit_cfg->stringValue());
330 if (!time_series_ref) {
331 time_series_ref = std::make_shared<ProtectedTimeSeries>();
333 time_series = time_series_ref;
337 TimePoint const now(std::chrono::system_clock::now());
345 while (!time_series->time_points_.empty()) {
346 if (time_series->time_points_.back() + limit.
time_unit_ < now) {
347 time_series->time_points_.pop_back();
358 time_series->time_points_.push_front(now);
394 template <isc::util::DhcpSpace D>
416 auto const& classes(packet->getClasses());
419 addClientClassesToLeaseContext(classes, lease);
429 auto const& relations(packet->getSubClassesRelations());
433 isc::data::ElementPtr client_class_limits = clientClassLimitsToElement<D>(relations, lease->getType());
439 if (!client_class_limits->empty()) {
440 limits->set(
"client-classes", client_class_limits);
442 if (!subnet_limit->empty()) {
443 limits->set(
"subnet", subnet_limit);
451 ISC->set(
"limits",
limits);
453 context->set(
"ISC", ISC);
456 std::string
const limit_exceeded_text(checkLeaseLimits<D>(context));
457 if (limit_exceeded_text.empty()) {
465 .arg(limit_exceeded_text);
490 template <isc::util::DhcpSpace D>
504 template <isc::util::DhcpSpace D>
515 template <isc::util::DhcpSpace D>
529 template <isc::util::DhcpSpace D>
535 template <isc::util::DhcpSpace D>
536 void recountClassLeases()
const;
540 std::unordered_map<isc::dhcp::ClientClass, TimeSeries> clocked_in_times_by_class_;
544 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 TrackingLeaseMgr & instance()
Return current lease manager.
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.
void setArgument(const std::string &name, T value)
Set argument.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#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.