Kea 2.7.7
network_state.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2025 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
11#include <dhcpsrv/timer_mgr.h>
13#include <boost/enable_shared_from_this.hpp>
14#include <functional>
15#include <sstream>
16#include <string>
17#include <unordered_set>
18
19using namespace isc::data;
20using namespace isc::util;
21
22namespace isc {
23namespace dhcp {
24
26class NetworkStateImpl : public boost::enable_shared_from_this<NetworkStateImpl>,
27 public CfgToElement {
28public:
29
35
38 for (auto const& origin : disabled_by_origin_) {
39 destroyTimer(origin);
40 }
41 }
42
55 void setDisableService(const bool disable, unsigned int origin) {
56 if (disable) {
57 // Disable the service for any flag.
58 globally_disabled_ = true;
59 disabled_by_origin_.insert(origin);
60 } else {
61 disabled_by_origin_.erase(origin);
62 // Enable the service only if all flags have been cleared.
63 if (disabled_by_origin_.empty()) {
64 globally_disabled_ = false;
65 }
66 }
67 }
68
73 auto disabled_by_origin = disabled_by_origin_;
74 for (auto const& origin : disabled_by_origin) {
75 if (origin >= NetworkState::DB_CONNECTION) {
76 disabled_by_origin_.erase(origin);
77 }
78 }
79 if (disabled_by_origin_.empty()) {
80 globally_disabled_ = false;
81 }
82 }
83
88 auto disabled_by_origin = disabled_by_origin_;
89 for (auto const& origin : disabled_by_origin) {
90 if (origin >= NetworkState::HA_LOCAL_COMMAND &&
92 disabled_by_origin_.erase(origin);
93 }
94 }
95 if (disabled_by_origin_.empty()) {
96 globally_disabled_ = false;
97 }
98 }
99
104 auto disabled_by_origin = disabled_by_origin_;
105 for (auto const& origin : disabled_by_origin) {
106 if (origin >= NetworkState::HA_REMOTE_COMMAND &&
108 disabled_by_origin_.erase(origin);
109 }
110 }
111 if (disabled_by_origin_.empty()) {
112 globally_disabled_ = false;
113 }
114 }
115
121 void delayedEnable(unsigned int origin) {
122 setDisableService(false, origin);
123 destroyTimer(origin);
124 }
125
135 void createTimer(const unsigned int seconds, unsigned int origin) {
136 destroyTimer(origin);
137 if (origin >= NetworkState::DB_CONNECTION) {
138 isc_throw(BadValue, "DB connection does not support delayed enable");
139 }
140 auto timer_name = getTimerName(origin);
141 timer_mgr_->registerTimer(timer_name,
143 shared_from_this(), origin),
144 seconds * 1000,
146 timer_mgr_->setup(timer_name);
147 }
148
152 void destroyTimer(unsigned int origin) {
153 if (origin >= NetworkState::DB_CONNECTION) {
154 return;
155 }
156 auto timer_name = getTimerName(origin);
157 if (timer_mgr_->isTimerRegistered(timer_name)) {
158 timer_mgr_->unregisterTimer(timer_name);
159 }
160 }
161
166 std::string getTimerName(unsigned int origin) const {
167 std::ostringstream timer_name;
168 timer_name << "network-state-timer-" << origin;
169 return (timer_name.str());
170 }
171
175 virtual ElementPtr toElement() const {
177 result->set("globally-disabled", Element::create(globally_disabled_));
178 bool disabled_by_user = false;
179 ElementPtr local_origin = Element::createList();
180 ElementPtr remote_origin = Element::createList();
181 ElementPtr db_origin = Element::createList();
182 std::set<unsigned int> ordered(disabled_by_origin_.begin(), disabled_by_origin_.end());
183 for (auto const& origin : ordered) {
184 if (origin == NetworkState::USER_COMMAND) {
185 disabled_by_user = true;
186 }
188 local_origin->add(Element::create(origin));
189 }
191 remote_origin->add(Element::create(origin));
192 }
193 if (origin >= NetworkState::DB_CONNECTION) {
194 db_origin->add(Element::create(origin));
195 }
196 }
197 result->set("disabled-by-user", Element::create(disabled_by_user));
198 result->set("disabled-by-local-command", local_origin);
199 result->set("disabled-by-remote-command", remote_origin);
200 result->set("disabled-by-db-connection", db_origin);
201
202 return (result);
203 }
204
207
210
213
219
221 std::unordered_set<unsigned int> disabled_by_origin_;
222};
223
225 : impl_(new NetworkStateImpl()), mutex_(new std::mutex()) {
226}
227
228void
229NetworkState::disableService(unsigned int origin) {
230 MultiThreadingLock lock(*mutex_);
231 impl_->setDisableService(true, origin);
232}
233
234void
235NetworkState::enableService(unsigned int origin) {
236 MultiThreadingLock lock(*mutex_);
237 impl_->delayedEnable(origin);
238}
239
240void
242 MultiThreadingLock lock(*mutex_);
243 impl_->resetForDbConnection();
244}
245
246void
248 MultiThreadingLock lock(*mutex_);
249 impl_->resetForLocalCommands();
250}
251
252void
254 MultiThreadingLock lock(*mutex_);
255 impl_->resetForRemoteCommands();
256}
257
258void
259NetworkState::delayedEnableService(const unsigned int seconds, unsigned int origin) {
260 MultiThreadingLock lock(*mutex_);
261 impl_->createTimer(seconds, origin);
262}
263
264bool
266 MultiThreadingLock lock(*mutex_);
267 return (!impl_->globally_disabled_);
268}
269
270bool
272 for (auto const& origin : impl_->disabled_by_origin_) {
273 if (TimerMgr::instance()->isTimerRegistered(impl_->getTimerName(origin))) {
274 return (true);
275 }
276 }
277 return (false);
278}
279
280void
282 isc_throw(NotImplemented, "selectiveDisableService is not implemented");
283}
284
285void
287 isc_throw(NotImplemented, "selectiveDisableService is not implemented");
288}
289
290void
292 isc_throw(NotImplemented, "selectiveEnableService is not implemented");
293}
294
295void
297 isc_throw(NotImplemented, "selectiveEnableService is not implemented");
298}
299
301 MultiThreadingLock lock(*mutex_);
302 return (impl_->toElement());
303}
304
305} // end of namespace isc::dhcp
306} // end of namespace isc
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown when a function is not implemented.
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 ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
Implementation of the NetworkState class.
void resetForDbConnection()
Reset internal counters for a database connection origin.
std::string getTimerName(unsigned int origin) const
Creates a unique timer name from the origin.
void setDisableService(const bool disable, unsigned int origin)
Sets appropriate disabled or enabled DHCP service state for the respective origin.
NetworkState::Subnets disabled_subnets_
A list of subnets for which the DHCP service has been disabled.
virtual ElementPtr toElement() const
The network state as Element.
void resetForRemoteCommands()
Reset origin for remote commands.
bool globally_disabled_
A flag indicating if DHCP service is globally disabled.
TimerMgrPtr timer_mgr_
A pointer to the common timer manager.
void delayedEnable(unsigned int origin)
Enables DHCP service for an origin.
std::unordered_set< unsigned int > disabled_by_origin_
A set of requests to disable the service by origin.
NetworkState::Networks disabled_networks_
A list of networks for which the DHCP service has been disabled.
void createTimer(const unsigned int seconds, unsigned int origin)
Creates a timer counting the time when delayedEnable should be automatically called.
void destroyTimer(unsigned int origin)
Destroys a timer if present.
void resetForLocalCommands()
Reset origin for local commands.
static const unsigned int DB_CONNECTION
The network state is being altered by the DB connection recovery mechanics.
void selectiveDisable(const NetworkState::Subnets &subnets)
Disable DHCP service for selected subnets.
virtual isc::data::ElementPtr toElement() const
The network state as Element.
static const unsigned int USER_COMMAND
Origin of the network state transition.
std::set< SubnetID > Subnets
Type of the container holding collection of subnet identifiers.
std::set< std::string > Networks
Type of the container holding collection of shared network names.
static const unsigned int HA_LOCAL_COMMAND
The network state is being altered by an HA internal command.
bool isDelayedEnableService() const
Checks if delayed enabling of DHCP services is scheduled.
static const unsigned int HA_REMOTE_COMMAND
The network state is being altered by a "dhcp-disable" or "dhcp-enable" command sent by a HA partner.
void resetForDbConnection()
Reset internal counters for database connection.
void resetForLocalCommands()
Reset origins for local commands.
void selectiveEnable(const NetworkState::Subnets &subnets)
Enable DHCP service for selected subnets.
void enableService(unsigned int origin)
Enable the DHCP service state for respective transition origin.
void disableService(unsigned int origin)
Disable the DHCP service state for respective transition origin.
bool isServiceEnabled() const
Checks if the DHCP service is globally enabled.
void delayedEnableService(const unsigned int seconds, unsigned int origin)
Schedules enabling DHCP service in the future.
void resetForRemoteCommands()
Reset origins for remote commands.
Manages a pool of asynchronous interval timers.
Definition timer_mgr.h:62
static const TimerMgrPtr & instance()
Returns pointer to the sole instance of the TimerMgr.
Definition timer_mgr.cc:446
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
boost::shared_ptr< TimerMgr > TimerMgrPtr
Type definition of the shared pointer to TimerMgr.
Definition timer_mgr.h:27
Defines the logger used by the top-level component of kea-lfc.
Abstract class for configuration Cfg_* classes.
RAII lock object to protect the code in the same scope with a mutex.