Kea 2.7.5
shared_network.cc
Go to the documentation of this file.
1// Copyright (C) 2017-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
11#include <boost/make_shared.hpp>
12
13using namespace isc;
14using namespace isc::data;
15using namespace isc::dhcp;
16
17namespace {
18
25class Impl {
26public:
27
45 template<typename SubnetPtrType, typename SubnetCollectionType>
46 static void add(SubnetCollectionType& subnets, const SubnetPtrType& subnet) {
47 // Subnet must be non-null.
48 if (!subnet) {
49 isc_throw(BadValue, "null pointer specified when adding a subnet"
50 " to a shared network");
51 }
52
53 // Check if a subnet with this id already exists.
54 if (getSubnet<SubnetPtrType>(subnets, subnet->getID())) {
55 isc_throw(DuplicateSubnetID, "attempted to add subnet with a"
56 " duplicated subnet identifier " << subnet->getID());
57 } else if (getSubnet<SubnetPtrType>(subnets, subnet->toText())) {
58 isc_throw(DuplicateSubnetID, "attempted to add subnet with a"
59 " duplicated subnet prefix " << subnet->toText());
60 }
61
62 // Check if the subnet is already associated with some network.
63 NetworkPtr network;
64 subnet->getSharedNetwork(network);
65 if (network) {
66 isc_throw(InvalidOperation, "subnet " << subnet->getID()
67 << " being added to a shared network"
68 " already belongs to a shared network");
69 }
70
71 // Add a subnet to the collection of subnets for this shared network.
72 static_cast<void>(subnets.insert(subnet));
73 }
74
95 template<typename SubnetPtrType, typename SubnetCollectionType>
96 static bool replace(SubnetCollectionType& subnets,
97 const SubnetPtrType& subnet) {
98
99 // Check if the new subnet is already associated with some network.
100 NetworkPtr network;
101 subnet->getSharedNetwork(network);
102 if (network) {
103 isc_throw(InvalidOperation, "subnet " << subnet->getID()
104 << " being replaced in a shared network"
105 " already belongs to a shared network");
106 }
107
108 // Get the subnet with the same ID.
109 const SubnetID& subnet_id = subnet->getID();
110 auto& index = subnets.template get<SubnetSubnetIdIndexTag>();
111 auto subnet_it = index.find(subnet_id);
112 if (subnet_it == index.end()) {
113 // Nothing to replace: return false to get the whole operation
114 // to be rollbacked.
115 return (false);
116 }
117
118 // Replace it.
119 return (index.replace(subnet_it, subnet));
120 }
121
132 template<typename SubnetPtrType, typename SubnetCollectionType>
133 static SubnetPtrType del(SubnetCollectionType& subnets,
134 const SubnetID& subnet_id) {
135 auto& index = subnets.template get<SubnetSubnetIdIndexTag>();
136 auto subnet_it = index.find(subnet_id);
137 if (subnet_it == index.end()) {
138 isc_throw(BadValue, "unable to delete subnet " << subnet_id
139 << " from shared network. Subnet doesn't belong"
140 " to this shared network");
141 }
142 auto subnet = *subnet_it;
143 index.erase(subnet_it);
144 return (subnet);
145 }
146
158 template<typename SubnetPtrType, typename SubnetCollectionType>
159 static SubnetPtrType getSubnet(const SubnetCollectionType& subnets,
160 const SubnetID& subnet_id) {
161 auto const& index = subnets.template get<SubnetSubnetIdIndexTag>();
162 auto subnet_it = index.find(subnet_id);
163 if (subnet_it != index.cend()) {
164 return (*subnet_it);
165 }
166
167 // Subnet not found.
168 return (SubnetPtrType());
169 }
170
183 template<typename SubnetPtrType, typename SubnetCollectionType>
184 static SubnetPtrType getSubnet(const SubnetCollectionType& subnets,
185 const std::string& subnet_prefix) {
186 auto const& index = subnets.template get<SubnetPrefixIndexTag>();
187 auto subnet_it = index.find(subnet_prefix);
188 if (subnet_it != index.cend()) {
189 return (*subnet_it);
190 }
191
192 // Subnet not found.
193 return (SubnetPtrType());
194 }
195
235 template<typename SubnetPtrType, typename SubnetCollectionType>
236 static SubnetPtrType getNextSubnet(const SubnetCollectionType& subnets,
237 const SubnetPtrType& first_subnet,
238 const SubnetID& current_subnet) {
239 // It is ok to have a shared network without any subnets, but in this
240 // case there is nothing else we can return but null pointer.
241 if (subnets.empty()) {
242 return (SubnetPtrType());
243 }
244
245 // Need to retrieve an iterator to the current subnet first. The
246 // subnet must exist in this container, thus we throw if the iterator
247 // is not found.
248 auto const& index = subnets.template get<SubnetSubnetIdIndexTag>();
249 auto subnet_it = index.find(current_subnet);
250 if (subnet_it == index.cend()) {
251 isc_throw(BadValue, "no such subnet " << current_subnet
252 << " within shared network");
253 }
254
255 // Step to a next subnet.
256 if (++subnet_it == subnets.cend()) {
257 // If we reached the end of the container, start over from the
258 // beginning.
259 subnet_it = subnets.cbegin();
260 }
261
262 // Check if we have made a full circle. If we did, return a null pointer
263 // to indicate that there are no more subnets.
264 if ((*subnet_it)->getID() == first_subnet->getID()) {
265 return (SubnetPtrType());
266 }
267
268 // Got the next subnet, so return it.
269 return (*subnet_it);
270 }
271
300 template<typename SubnetPtrType, typename SubnetCollectionType>
301 static SubnetPtrType getPreferredSubnet(const SubnetCollectionType& subnets,
302 const SubnetPtrType& selected_subnet,
303 const Lease::Type& lease_type) {
304
305 auto preferred_subnet = selected_subnet;
306 for (auto const& s : subnets) {
307 // It doesn't make sense to check the subnet against itself.
308 if (preferred_subnet == s) {
309 continue;
310 }
311 if (s->getClientClass().get() != selected_subnet->getClientClass().get()) {
312 continue;
313 }
314 auto current_subnet_state = s->getAllocationState(lease_type);
315 if (!current_subnet_state) {
316 continue;
317 }
318 auto preferred_subnet_state = preferred_subnet->getAllocationState(lease_type);
319 if (!preferred_subnet_state) {
320 continue;
321 }
322 // The currently checked subnet has more recent time than the
323 // currently preferred subnet. Update the preferred subnet
324 // instance.
325 if (current_subnet_state->getLastAllocatedTime() >
326 preferred_subnet_state->getLastAllocatedTime()) {
327 preferred_subnet = s;
328 }
329 }
330 return (preferred_subnet);
331 }
332};
333
334} // end of anonymous namespace
335
336namespace isc {
337namespace dhcp {
338
340SharedNetwork4::create(const std::string& name) {
341 return (boost::make_shared<SharedNetwork4>(name));
342}
343
344void
346 Impl::add(subnets_, subnet);
347 // Associate the subnet with this network.
348 subnet->setSharedNetwork(shared_from_this());
349 subnet->setSharedNetworkName(name_);
350}
351
352bool
354 // Subnet must be non-null.
355 if (!subnet) {
356 isc_throw(BadValue, "null pointer specified when adding a subnet"
357 " to a shared network");
358 }
359 const Subnet4Ptr& old = getSubnet(subnet->getID());
360 bool ret = Impl::replace(subnets_, subnet);
361 if (ret) {
362 // Associate the subnet with this network.
363 subnet->setSharedNetwork(shared_from_this());
364 subnet->setSharedNetworkName(name_);
365 // Deassociate the previous subnet.
366 old->setSharedNetwork(NetworkPtr());
367 old->setSharedNetworkName("");
368 }
369 return (ret);
370}
371
372void
373SharedNetwork4::del(const SubnetID& subnet_id) {
374 Subnet4Ptr subnet = Impl::del<Subnet4Ptr>(subnets_, subnet_id);
375 subnet->setSharedNetwork(NetworkPtr());
376 subnet->setSharedNetworkName("");
377}
378
379void
381 for (auto const& subnet : subnets_) {
382 subnet->setSharedNetwork(NetworkPtr());
383 subnet->setSharedNetworkName("");
384 }
385 subnets_.clear();
386}
387
389SharedNetwork4::getSubnet(const SubnetID& subnet_id) const {
390 return (Impl::getSubnet<Subnet4Ptr>(subnets_, subnet_id));
391}
392
394SharedNetwork4::getSubnet(const std::string& subnet_prefix) const {
395 return (Impl::getSubnet<Subnet4Ptr>(subnets_, subnet_prefix));
396}
397
400 const SubnetID& current_subnet) const {
401 return (Impl::getNextSubnet(subnets_, first_subnet, current_subnet));
402}
403
406 return (Impl::getPreferredSubnet(subnets_, selected_subnet, Lease::TYPE_V4));
407}
408
409bool
411 const ClientClasses& client_classes) {
412 for (ConstSubnet4Ptr subnet = first_subnet; subnet;
413 subnet = subnet->getNextSubnet(first_subnet, client_classes)) {
414 if (subnet->getMatchClientId()) {
415 return (true);
416 }
417 }
418 return (false);
419}
420
424
425 // Set shared network name.
426 if (!name_.empty()) {
427 map->set("name", Element::create(name_));
428 }
429
431 for (auto const& subnet : subnets_) {
432 subnet4->add(subnet->toElement());
433 }
434
435 map->set("subnet4", subnet4);
436
437 return (map);
438}
439
441SharedNetwork6::create(const std::string& name) {
442 return (boost::make_shared<SharedNetwork6>(name));
443}
444
445void
447 Impl::add(subnets_, subnet);
448 // Associate the subnet with this network.
449 subnet->setSharedNetwork(shared_from_this());
450 subnet->setSharedNetworkName(name_);
451}
452
453bool
455 // Subnet must be non-null.
456 if (!subnet) {
457 isc_throw(BadValue, "null pointer specified when adding a subnet"
458 " to a shared network");
459 }
460 const Subnet6Ptr& old = getSubnet(subnet->getID());
461 bool ret = Impl::replace(subnets_, subnet);
462 if (ret) {
463 // Associate the subnet with this network.
464 subnet->setSharedNetwork(shared_from_this());
465 subnet->setSharedNetworkName(name_);
466 // Deassociate the previous subnet.
467 old->setSharedNetwork(NetworkPtr());
468 old->setSharedNetworkName("");
469 }
470 return (ret);
471}
472
473void
474SharedNetwork6::del(const SubnetID& subnet_id) {
475 Subnet6Ptr subnet = Impl::del<Subnet6Ptr>(subnets_, subnet_id);
476 subnet->setSharedNetwork(NetworkPtr());
477 subnet->setSharedNetworkName("");
478}
479
480void
482 for (auto const& subnet : subnets_) {
483 subnet->setSharedNetwork(NetworkPtr());
484 }
485 subnets_.clear();
486}
487
489SharedNetwork6::getSubnet(const SubnetID& subnet_id) const {
490 return (Impl::getSubnet<Subnet6Ptr>(subnets_, subnet_id));
491}
492
494SharedNetwork6::getSubnet(const std::string& subnet_prefix) const {
495 return (Impl::getSubnet<Subnet6Ptr>(subnets_, subnet_prefix));
496}
497
500 const SubnetID& current_subnet) const {
501 return (Impl::getNextSubnet(subnets_, first_subnet, current_subnet));
502}
503
506 const Lease::Type& lease_type) const {
507 return (Impl::getPreferredSubnet(subnets_, selected_subnet, lease_type));
508}
509
513
514 // Set shared network name.
515 if (!name_.empty()) {
516 map->set("name", Element::create(name_));
517 }
518
520 for (auto const& subnet : subnets_) {
521 subnet6->add(subnet->toElement());
522 }
523
524 map->set("subnet6", subnet6);
525
526 return (map);
527}
528
529} // end of namespace isc::dhcp
530} // 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 if a function is called in a prohibited way.
static ElementPtr create(const Position &pos=ZERO_POSITION())
Definition data.cc:249
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition data.cc:299
Container for storing client class names.
Definition classify.h:108
Exception thrown upon attempt to add subnet with an ID that belongs to the subnet that already exists...
Definition subnet_id.h:36
virtual data::ElementPtr toElement() const
Unparses network object.
Definition network.cc:298
virtual data::ElementPtr toElement() const
Unparses network object.
Definition network.cc:350
bool replace(const Subnet4Ptr &subnet)
Replaces IPv4 subnet in a shared network.
static SharedNetwork4Ptr create(const std::string &name)
Factory function creating an instance of the SharedNetwork4.
ConstSubnet4Ptr getNextSubnet(const ConstSubnet4Ptr &first_subnet, const SubnetID &current_subnet) const
Retrieves next available IPv4 subnet within shared network.
ConstSubnet4Ptr getPreferredSubnet(const ConstSubnet4Ptr &selected_subnet) const
Attempts to find a subnet which is more likely to include available leases than selected subnet.
virtual data::ElementPtr toElement() const
Unparses shared network object.
void add(const Subnet4Ptr &subnet)
Adds IPv4 subnet to a shared network.
void del(const SubnetID &subnet_id)
Removes subnet from a shared network.
Subnet4Ptr getSubnet(const SubnetID &subnet_id) const
Returns a subnet for a specified subnet id.
void delAll()
Removes all subnets from a shared network.
static bool subnetsIncludeMatchClientId(const ConstSubnet4Ptr &first_subnet, const ClientClasses &client_classes)
Checks if the shared network includes a subnet with the match client ID flag set to true.
static SharedNetwork6Ptr create(const std::string &name)
Factory function creating an instance of the SharedNetwork6.
ConstSubnet6Ptr getPreferredSubnet(const ConstSubnet6Ptr &selected_subnet, const Lease::Type &lease_type) const
Attempts to find a subnet which is more likely to include available leases than selected subnet.
Subnet6Ptr getSubnet(const SubnetID &subnet_id) const
Returns a subnet for a specified subnet id.
void del(const SubnetID &subnet_id)
Removes subnet from a shared network.
void add(const Subnet6Ptr &subnet)
Adds IPv6 subnet to a shared network.
ConstSubnet6Ptr getNextSubnet(const ConstSubnet6Ptr &first_subnet, const SubnetID &current_subnet) const
Retrieves next available IPv6 subnet within shared network.
virtual data::ElementPtr toElement() const
Unparses shared network object.
bool replace(const Subnet6Ptr &subnet)
Replaces IPv6 subnet in a shared network.
void delAll()
Removes all subnets from a shared network.
#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< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
Definition subnet.h:461
boost::shared_ptr< const Subnet6 > ConstSubnet6Ptr
A const pointer to a Subnet6 object.
Definition subnet.h:623
boost::shared_ptr< const Subnet4 > ConstSubnet4Ptr
A const pointer to a Subnet4 object.
Definition subnet.h:458
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
Definition subnet.h:626
boost::shared_ptr< SharedNetwork6 > SharedNetwork6Ptr
Pointer to SharedNetwork6 object.
uint32_t SubnetID
Defines unique IPv4 or IPv6 subnet identifier.
Definition subnet_id.h:25
boost::shared_ptr< Network > NetworkPtr
Pointer to the Network object.
Definition network.h:73
boost::shared_ptr< SharedNetwork4 > SharedNetwork4Ptr
Pointer to SharedNetwork4 object.
Defines the logger used by the top-level component of kea-lfc.
Type
Type of lease or pool.
Definition lease.h:46
@ TYPE_V4
IPv4 lease.
Definition lease.h:50