Kea 2.7.0
perfmon_config.cc
Go to the documentation of this file.
1// Copyright (C) 2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <perfmon_config.h>
10#include <dhcp/dhcp6.h>
11#include <dhcp/pkt4.h>
12#include <dhcp/pkt6.h>
13
14using namespace isc;
15using namespace isc::data;
16using namespace isc::dhcp;
17using namespace boost::posix_time;
18
19namespace isc {
20namespace perfmon {
21
24{
25 {"query-type", Element::string},
26 {"response-type", Element::string},
27 {"start-event", Element::string},
28 {"stop-event", Element::string},
29 {"subnet-id", Element::integer}
30};
31
32uint16_t
34 static std::map<std::string, uint16_t> name_type_map = {
35 {"", DHCP_NOTYPE},
36 {"*", DHCP_NOTYPE},
37 {"DHCPDISCOVER", DHCPDISCOVER},
38 {"DHCPOFFER", DHCPOFFER},
39 {"DHCPREQUEST", DHCPREQUEST},
40 {"DHCPDECLINE", DHCPDECLINE},
41 {"DHCPACK", DHCPACK},
42 {"DHCPNAK", DHCPNAK},
43 {"DHCPRELEASE", DHCPRELEASE},
44 {"DHCPINFORM", DHCPINFORM},
45 {"DHCPLEASEQUERY", DHCPLEASEQUERY},
46 {"DHCPLEASEUNASSIGNED", DHCPLEASEUNASSIGNED},
47 {"DHCPLEASEUNKNOWN", DHCPLEASEUNKNOWN},
48 {"DHCPLEASEACTIVE", DHCPLEASEACTIVE},
49 {"DHCPBULKLEASEQUERY", DHCPBULKLEASEQUERY},
50 {"DHCPLEASEQUERYDONE", DHCPLEASEQUERYDONE},
51 {"DHCPLEASEQUERYSTATUS", DHCPLEASEQUERYSTATUS},
52 {"DHCPTLS", DHCPTLS}
53 };
54
55 try {
56 const auto& found = name_type_map.at(name);
57 return (found);
58 } catch (const std::out_of_range& ex) {
59 isc_throw(BadValue, "'" << name << "' is not a valid DHCP message type");
60 }
61}
62
63uint16_t
65 static std::map<std::string, uint16_t> name_type_map = {
66 {"", DHCPV6_NOTYPE},
67 {"*", DHCPV6_NOTYPE},
68 {"SOLICIT", DHCPV6_SOLICIT},
69 {"ADVERTISE", DHCPV6_ADVERTISE},
70 {"REQUEST", DHCPV6_REQUEST},
71 {"CONFIRM", DHCPV6_CONFIRM},
72 {"RENEW", DHCPV6_RENEW},
73 {"REBIND", DHCPV6_REBIND},
74 {"REPLY", DHCPV6_REPLY},
75 {"RELEASE", DHCPV6_RELEASE},
76 {"DECLINE", DHCPV6_DECLINE},
77 {"RECONFIGURE", DHCPV6_RECONFIGURE},
78 {"INFORMATION_REQUEST", DHCPV6_INFORMATION_REQUEST},
79 {"RELAY_FORW", DHCPV6_RELAY_FORW},
80 {"RELAY_REPL", DHCPV6_RELAY_REPL},
81 {"LEASEQUERY", DHCPV6_LEASEQUERY},
82 {"LEASEQUERY_REPLY", DHCPV6_LEASEQUERY_REPLY},
83 {"LEASEQUERY_DONE", DHCPV6_LEASEQUERY_DONE},
84 {"LEASEQUERY_DATA", DHCPV6_LEASEQUERY_DATA},
85 {"RECONFIGURE_REQUEST", DHCPV6_RECONFIGURE_REQUEST},
86 {"RECONFIGURE_REPLY", DHCPV6_RECONFIGURE_REPLY},
87 {"DHCPV4_QUERY", DHCPV6_DHCPV4_QUERY},
88 {"DHCPV4_RESPONSE", DHCPV6_DHCPV4_RESPONSE},
89 {"ACTIVELEASEQUERY", DHCPV6_ACTIVELEASEQUERY},
90 {"STARTTLS", DHCPV6_STARTTLS},
91 {"BNDUPD", DHCPV6_BNDUPD},
92 {"BNDREPLY", DHCPV6_BNDREPLY},
93 {"POOLREQ", DHCPV6_POOLREQ},
94 {"POOLRESP", DHCPV6_POOLRESP},
95 {"UPDREQ", DHCPV6_UPDREQ},
96 {"UPDREQALL", DHCPV6_UPDREQALL},
97 {"UPDDONE", DHCPV6_UPDDONE},
98 {"CONNECT", DHCPV6_CONNECT},
99 {"CONNECTREPLY", DHCPV6_CONNECTREPLY},
100 {"DISCONNECT", DHCPV6_DISCONNECT},
101 {"STATE", DHCPV6_STATE},
102 {"CONTACT", DHCPV6_CONTACT}
103 };
104
105 try {
106 const auto& found = name_type_map.at(name);
107 return (found);
108 } catch (const std::out_of_range& ex) {
109 isc_throw(BadValue, "'" << name << "' is not a valid DHCPV6 message type");
110 }
111}
112
113uint16_t
115 uint16_t family,
116 const std::string& param_name,
117 bool required /*= true */) {
118 // Parse members.
119 uint16_t msg_type = 0;
120 ConstElementPtr elem = config->get(param_name);
121 if (elem) {
122 try {
123 msg_type = (family == AF_INET ? getMessageNameType4(elem->stringValue())
124 : getMessageNameType6(elem->stringValue()));
125 } catch (const std::exception& ex) {
126 isc_throw(DhcpConfigError, "'" << param_name << "' parameter is invalid, " << ex.what());
127 }
128 } else {
129 if (required) {
130 isc_throw(DhcpConfigError, "'" << param_name << "' parameter is required");
131 }
132 }
133
134 return (msg_type);
135}
136
139 // Note checkKeywords() will throw DhcpConfigError if there is a problem.
141
142 // Parse members.
143 auto query_type = getMessageType(config, family, "query-type");
144
145 auto response_type = getMessageType(config, family, "response-type");
146
147 std::string start_event;
148 ConstElementPtr elem = config->get("start-event");
149 if (elem) {
150 start_event = elem->stringValue();
151 } else {
152 isc_throw(DhcpConfigError, "'start-event' parameter is required");
153 }
154
155 std::string stop_event;
156 elem = config->get("stop-event");
157 if (elem) {
158 stop_event = elem->stringValue();
159 } else {
160 isc_throw(DhcpConfigError, "'stop-event' parameter is required");
161 }
162
163 SubnetID subnet_id = SUBNET_ID_GLOBAL;
164 elem = config->get("subnet-id");
165 if (elem) {
166 subnet_id = static_cast<SubnetID>(elem->intValue());
167 }
168
169 return (DurationKeyPtr(new DurationKey(family, query_type, response_type,
170 start_event, stop_event, subnet_id)));
171}
172
175 if (!key) {
176 isc_throw(BadValue, "DurationKeyParser::toElement() - key is empty");
177 }
178
180 if (key->getFamily() == AF_INET) {
181 map->set("query-type", Element::create(Pkt4::getName(key->getQueryType())));
182 map->set("response-type", Element::create(Pkt4::getName(key->getResponseType())));
183 } else {
184 map->set("query-type", Element::create(Pkt6::getName(key->getQueryType())));
185 map->set("response-type", Element::create(Pkt6::getName(key->getResponseType())));
186 }
187
188 map->set("start-event", Element::create(key->getStartEventLabel()));
189 map->set("stop-event", Element::create(key->getStopEventLabel()));
190 map->set("subnet-id", Element::create(static_cast<long long>(key->getSubnetId())));
191 return (map);
192}
193
196{
197 {"duration-key", Element::map},
198 {"enable-alarm", Element::boolean},
199 {"high-water-ms", Element::integer},
200 {"low-water-ms", Element::integer}
201};
202
205 // Note checkKeywords() will throw DhcpConfigError if there is a problem.
207
208 // First parse the duration-key.
209 ConstElementPtr elem = config->get("duration-key");
210 if (!elem) {
211 isc_throw(DhcpConfigError, "'duration-key'" <<" parameter is required");
212 }
213
214 DurationKeyPtr key = DurationKeyParser::parse(elem, family);
215
216 // Parse scalar members.
217 elem = config->get("enable-alarm");
218 bool enable_alarm = (elem ? elem->boolValue() : true);
219
220 elem = config->get("high-water-ms");
221 uint64_t high_water_ms = 0;
222 if (elem) {
223 int64_t value = elem->intValue();
224 if (value <= 0) {
225 isc_throw(DhcpConfigError, "high-water-ms: '"
226 << value << "', must be greater than 0");
227 }
228
229 high_water_ms = value;
230 } else {
231 isc_throw(DhcpConfigError, "'high-water-ms'" <<" parameter is required");
232 }
233
234 elem = config->get("low-water-ms");
235 uint64_t low_water_ms = 0;
236 if (elem) {
237 int64_t value = elem->intValue();
238 if (value <= 0) {
239 isc_throw(DhcpConfigError, "low-water-ms: '"
240 << value << "', must be greater than 0");
241 }
242
243 low_water_ms = value;
244 } else {
245 isc_throw(DhcpConfigError, "'low-water-ms'" <<" parameter is required");
246 }
247
248 if (low_water_ms >= high_water_ms) {
249 isc_throw(DhcpConfigError, "'low-water-ms': " << low_water_ms
250 << ", must be less than 'high-water-ms': " << high_water_ms);
251 }
252
253 return (AlarmPtr(new Alarm(*key, milliseconds(low_water_ms),
254 milliseconds(high_water_ms), enable_alarm)));
255}
256
259{
260 {"enable-monitoring", Element::boolean},
261 {"interval-width-secs", Element::integer},
262 {"stats-mgr-reporting", Element::boolean},
263 {"alarm-report-secs", Element::integer},
264 {"alarms", Element::list}
265};
266
268 : family_(family),
269 enable_monitoring_(false),
270 interval_width_secs_(60),
271 stats_mgr_reporting_(true),
272 alarm_report_secs_(300) {
273 if (family_ != AF_INET && family_ != AF_INET6) {
274 isc_throw (BadValue, "PerfmonConfig: family must be AF_INET or AF_INET6");
275 }
276
277 alarm_store_.reset(new AlarmStore(family_));
278}
279
280void
282 // Use a local instance to collect values. This way we
283 // avoid corrupting current values if there are any errors.
284 PerfMonConfig local(family_);
285
286 // Note checkKeywords() will throw DhcpConfigError if there is a problem.
288
289 // Parse members.
290 ConstElementPtr elem = config->get("enable-monitoring");
291 if (elem) {
292 local.setEnableMonitoring(elem->boolValue());
293 }
294
295 elem = config->get("interval-width-secs");
296 if (elem) {
297 int64_t value = elem->intValue();
298 if (value <= 0) {
299 isc_throw(DhcpConfigError, "invalid interval-width-secs: '"
300 << value << "', must be greater than 0");
301 }
302
303 local.setIntervalWidthSecs(value);
304 }
305
306 elem = config->get("stats-mgr-reporting");
307 if (elem) {
308 local.setStatsMgrReporting(elem->boolValue());
309 }
310
311 elem = config->get("alarm-report-secs");
312 if (elem) {
313 int64_t value = elem->intValue();
314 if (value < 0) {
315 isc_throw(DhcpConfigError, "invalid alarm-report-secs: '"
316 << value << "', cannot be less than 0");
317 }
318
319 local.setAlarmReportSecs(value);
320 }
321
322 elem = config->get("alarms");
323 if (elem) {
324 local.parseAlarms(elem);
325 }
326
327 // All values good, copy them from local instance.
328 family_= local.getFamily();
334}
335
336void
338 alarm_store_.reset(new AlarmStore(family_));
339 for (auto const& alarm_elem : config->listValue()) {
340 try {
341 AlarmPtr alarm = AlarmParser::parse(alarm_elem, family_);
342 alarm_store_->addAlarm(alarm);
343 } catch (const std::exception& ex) {
344 isc_throw(DhcpConfigError, "cannot add Alarm to store: " << ex.what());
345 }
346 }
347}
348
349} // end of namespace perfmon
350} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
static ElementPtr createMap(const Position &pos=ZERO_POSITION())
Creates an empty MapElement type ElementPtr.
Definition data.cc:304
static void checkKeywords(const SimpleKeywords &keywords, isc::data::ConstElementPtr scope)
Checks acceptable keywords with their expected type.
To be removed. Please use ConfigError instead.
const char * getName() const
Returns name of the DHCP message.
Definition pkt4.cc:365
const char * getName() const
Returns name of the DHCPv6 message.
Definition pkt6.cc:868
static const data::SimpleKeywords CONFIG_KEYWORDS
List of valid parameters and expected types.
static AlarmPtr parse(data::ConstElementPtr config, uint16_t family)
Maintains an in-memory store of alarms.
Definition alarm_store.h:74
Defines an alarm for a duration.
Definition alarm.h:20
static uint16_t getMessageType(data::ConstElementPtr config, uint16_t family, const std::string &param_name, bool required=true)
Convert a configuration parameter to family-specific message type.
static const data::SimpleKeywords CONFIG_KEYWORDS
List of valid parameters and expected types.
static data::ElementPtr toElement(DurationKeyPtr key)
Convert a DurationKey into a map of Elements.
static uint16_t getMessageNameType6(const std::string &name)
Convert string message name to DHCP6 message type.
static DurationKeyPtr parse(data::ConstElementPtr config, uint16_t family)
Convert a map of Elements into a DurationKey.
static uint16_t getMessageNameType4(const std::string &name)
Convert string message name to DHCP message type.
Houses the composite key that uniquely identifies a duration:
Houses the PerfMon configuration parameters for a single scope (e.g.
PerfMonConfig(uint16_t family)
Constructor.
uint32_t interval_width_secs_
Number of seconds a duration accumulates samples until reporting.
void setIntervalWidthSecs(uint32_t value)
Sets the value of interval-width-secs.
uint32_t alarm_report_secs_
Number of seconds between reports of a raised alarm.
bool getEnableMonitoring() const
Fetches the value of enable-monitoring.
void setEnableMonitoring(bool value)
Sets the value of enable-monitoring.
void parseAlarms(data::ConstElementPtr config)
Re-creates the AlarmStore and populates it by parsing a list of alarm elements.
void setStatsMgrReporting(bool value)
Sets the value of stats-mgr-reporting.
AlarmStorePtr getAlarmStore()
Get the alarm store.
uint16_t family_
Protocol family AF_INET or AF_INET6.
bool getStatsMgrReporting() const
Fetches the value of stats-mgr-reporting.
uint16_t getFamily()
Get protocol family.
void parse(data::ConstElementPtr config)
Extracts member values from an Element::map.
AlarmStorePtr alarm_store_
Stores the configured alarms.
std::atomic< bool > stats_mgr_reporting_
If true durations report to StatsMgr at the end of each interval.
uint32_t getAlarmReportSecs() const
Fetches the value of alarm-report-secs.
uint32_t getIntervalWidthSecs() const
Fetches the value of interval-width-secs.
void setAlarmReportSecs(uint32_t value)
Sets the value of alarm-report-secs.
static const data::SimpleKeywords CONFIG_KEYWORDS
List of valid parameters and expected types.
std::atomic< bool > enable_monitoring_
If true, performance data is processed/reported.
@ DHCPV6_ADVERTISE
Definition dhcp6.h:199
@ DHCPV6_CONNECTREPLY
Definition dhcp6.h:235
@ DHCPV6_CONTACT
Definition dhcp6.h:238
@ DHCPV6_UPDREQ
Definition dhcp6.h:231
@ DHCPV6_LEASEQUERY
Definition dhcp6.h:212
@ DHCPV6_REQUEST
Definition dhcp6.h:200
@ DHCPV6_UPDDONE
Definition dhcp6.h:233
@ DHCPV6_RELAY_REPL
Definition dhcp6.h:210
@ DHCPV6_RENEW
Definition dhcp6.h:202
@ DHCPV6_RECONFIGURE_REPLY
Definition dhcp6.h:219
@ DHCPV6_DHCPV4_QUERY
Definition dhcp6.h:221
@ DHCPV6_DHCPV4_RESPONSE
Definition dhcp6.h:222
@ DHCPV6_BNDUPD
Definition dhcp6.h:227
@ DHCPV6_RECONFIGURE
Definition dhcp6.h:207
@ DHCPV6_ACTIVELEASEQUERY
Definition dhcp6.h:224
@ DHCPV6_STARTTLS
Definition dhcp6.h:225
@ DHCPV6_REBIND
Definition dhcp6.h:203
@ DHCPV6_DISCONNECT
Definition dhcp6.h:236
@ DHCPV6_REPLY
Definition dhcp6.h:204
@ DHCPV6_POOLREQ
Definition dhcp6.h:229
@ DHCPV6_SOLICIT
Definition dhcp6.h:198
@ DHCPV6_RELEASE
Definition dhcp6.h:205
@ DHCPV6_LEASEQUERY_DATA
Definition dhcp6.h:216
@ DHCPV6_INFORMATION_REQUEST
Definition dhcp6.h:208
@ DHCPV6_BNDREPLY
Definition dhcp6.h:228
@ DHCPV6_CONNECT
Definition dhcp6.h:234
@ DHCPV6_STATE
Definition dhcp6.h:237
@ DHCPV6_CONFIRM
Definition dhcp6.h:201
@ DHCPV6_RECONFIGURE_REQUEST
Definition dhcp6.h:218
@ DHCPV6_LEASEQUERY_DONE
Definition dhcp6.h:215
@ DHCPV6_LEASEQUERY_REPLY
Definition dhcp6.h:213
@ DHCPV6_RELAY_FORW
Definition dhcp6.h:209
@ DHCPV6_POOLRESP
Definition dhcp6.h:230
@ DHCPV6_DECLINE
Definition dhcp6.h:206
@ DHCPV6_UPDREQALL
Definition dhcp6.h:232
@ DHCPV6_NOTYPE
Definition dhcp6.h:197
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
std::map< std::string, isc::data::Element::types > SimpleKeywords
This specifies all accepted keywords with their types.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
@ DHCPLEASEQUERYSTATUS
Definition dhcp4.h:251
@ DHCPTLS
Definition dhcp4.h:252
@ DHCPREQUEST
Definition dhcp4.h:237
@ DHCPLEASEQUERYDONE
Definition dhcp4.h:249
@ DHCPLEASEUNKNOWN
Definition dhcp4.h:246
@ DHCPOFFER
Definition dhcp4.h:236
@ DHCPLEASEACTIVE
Definition dhcp4.h:247
@ DHCPLEASEQUERY
Definition dhcp4.h:244
@ DHCPDECLINE
Definition dhcp4.h:238
@ DHCPNAK
Definition dhcp4.h:240
@ DHCPRELEASE
Definition dhcp4.h:241
@ DHCPLEASEUNASSIGNED
Definition dhcp4.h:245
@ DHCPDISCOVER
Definition dhcp4.h:235
@ DHCPBULKLEASEQUERY
Definition dhcp4.h:248
@ DHCP_NOTYPE
Message Type option missing.
Definition dhcp4.h:234
@ DHCPINFORM
Definition dhcp4.h:242
@ DHCPACK
Definition dhcp4.h:239
boost::shared_ptr< DurationKey > DurationKeyPtr
Defines a pointer to a DurationKey instance.
boost::shared_ptr< Alarm > AlarmPtr
Defines a pointer to an Alarm instance.
Definition alarm.h:168
Defines the logger used by the top-level component of kea-lfc.
The classes herein parse PerfMon hook library's 'parameters' element depicted below: