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>
141 const std::string
error(
"The lease database you have configured "
142 "does not support JSON operations which are required for lease "
150 recountClassLeases<D>();
155 ->getLeaseDbAccessString());
156 if (lease_db_access_string.find(
"retry-on-startup=true") &&
157 (lease_db_access_string.find(
"type=mysql") ||
158 lease_db_access_string.find(
"type=postgresql"))) {
179 template <isc::util::DhcpSpace D>
193 auto const& classes(packet->getClasses());
198 auto const& relations = packet->getSubClassesRelations();
201 TimePoint const now(std::chrono::system_clock::now());
204 std::vector<isc::dhcp::ClientClass> common_client_classes;
213 for (
auto const& c : relations) {
219 auto const &limit_cfg = rate_limit_configuration_.parseUserContext(class_def->getContext());
226 RateLimit const& limit(limit_cfg->stringValue());
229 TimeSeries& time_series(clocked_in_times_by_class_[c.class_]);
234 while (!time_series.empty()) {
235 if (time_series.back() + limit.
time_unit_ < now) {
236 time_series.pop_back();
251 .arg(classes.toText())
263 common_client_classes.push_back(c.class_);
269 stats_mgr.
addValue(
"pkt4-limit-exceeded",
270 static_cast<int64_t
>(1));
271 stats_mgr.
addValue(
"pkt4-receive-drop",
272 static_cast<int64_t
>(1));
274 stats_mgr.
addValue(
"pkt6-limit-exceeded",
275 static_cast<int64_t
>(1));
276 stats_mgr.
addValue(
"pkt6-receive-drop",
277 static_cast<int64_t
>(1));
281 for (
auto const& c : common_client_classes) {
282 TimeSeries& time_series(clocked_in_times_by_class_.at(c));
283 time_series.push_front(now);
287 if (!common_client_classes.empty()) {
290 .arg(classes.toText());
309 template <isc::util::DhcpSpace D>
328 auto const& limit_cfg = subnetRateLimit<D>(subnet_id);
331 limit =
RateLimit(limit_cfg->stringValue());
344 if (!time_series_ref) {
345 time_series_ref = std::make_shared<ProtectedTimeSeries>();
347 time_series = time_series_ref;
351 TimePoint const now(std::chrono::system_clock::now());
359 while (!time_series->time_points_.empty()) {
360 if (time_series->time_points_.back() + limit.
time_unit_ < now) {
361 time_series->time_points_.pop_back();
372 time_series->time_points_.push_front(now);
384 stats_mgr.
addValue(
"pkt4-limit-exceeded",
385 static_cast<int64_t
>(1));
386 stats_mgr.
addValue(
"pkt4-receive-drop",
387 static_cast<int64_t
>(1));
389 stats_mgr.
addValue(
"pkt6-limit-exceeded",
390 static_cast<int64_t
>(1));
391 stats_mgr.
addValue(
"pkt6-receive-drop",
392 static_cast<int64_t
>(1));
421 template <isc::util::DhcpSpace D>
443 auto const& classes(packet->getClasses());
446 addClientClassesToLeaseContext(classes, lease);
456 auto const& relations(packet->getSubClassesRelations());
460 isc::data::ElementPtr client_class_limits = clientClassLimitsToElement<D>(relations, lease->getType());
466 if (!client_class_limits->empty()) {
467 limits->set(
"client-classes", client_class_limits);
469 if (!subnet_limit->empty()) {
470 limits->set(
"subnet", subnet_limit);
478 ISC->set(
"limits",
limits);
480 context->set(
"ISC", ISC);
483 std::string
const limit_exceeded_text(checkLeaseLimits<D>(context));
484 if (limit_exceeded_text.empty()) {
492 .arg(limit_exceeded_text);
517 template <isc::util::DhcpSpace D>
531 template <isc::util::DhcpSpace D>
542 template <isc::util::DhcpSpace D>
556 template <isc::util::DhcpSpace D>
562 template <isc::util::DhcpSpace D>
563 void recountClassLeases()
const;
567 std::unordered_map<isc::dhcp::ClientClass, TimeSeries> clocked_in_times_by_class_;
571 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.
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.