Kea 1.5.0
shared_network.cc
Go to the documentation of this file.
1// Copyright (C) 2017-2018 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
12using namespace isc;
13using namespace isc::data;
14using namespace isc::dhcp;
15
16namespace {
17
24class Impl {
25public:
26
44 template<typename SubnetPtrType, typename SubnetCollectionType>
45 static void add(SubnetCollectionType& subnets, const SubnetPtrType& subnet) {
46 // Subnet must be non-null.
47 if (!subnet) {
48 isc_throw(BadValue, "null pointer specified when adding a subnet"
49 " to a shared network");
50 }
51
52 // Check if a subnet with this id already exists.
53 if (getSubnet<SubnetPtrType>(subnets, subnet->getID())) {
54 isc_throw(DuplicateSubnetID, "attempted to add subnet with a"
55 " duplicated subnet identifier " << subnet->getID());
56 }
57
58 // Check if the subnet is already associated with some network.
59 NetworkPtr network;
60 subnet->getSharedNetwork(network);
61 if (network) {
62 isc_throw(InvalidOperation, "subnet " << subnet->getID()
63 << " being added to a shared network"
64 " already belongs to a shared network");
65 }
66
67 // Add a subnet to the collection of subnets for this shared network.
68 subnets.push_back(subnet);
69 }
70
81 template<typename SubnetPtrType, typename SubnetCollectionType>
82 static SubnetPtrType del(SubnetCollectionType& subnets,
83 const SubnetID& subnet_id) {
84 auto& index = subnets.template get<SubnetSubnetIdIndexTag>();
85 auto subnet_it = index.find(subnet_id);
86 if (subnet_it == index.end()) {
87 isc_throw(BadValue, "unable to delete subnet " << subnet_id
88 << " from shared network. Subnet doesn't belong"
89 " to this shared network");
90 }
91 auto subnet = *subnet_it;
92 index.erase(subnet_it);
93 return (subnet);
94 }
95
107 template<typename SubnetPtrType, typename SubnetCollectionType>
108 static SubnetPtrType getSubnet(const SubnetCollectionType& subnets,
109 const SubnetID& subnet_id) {
110 const auto& index = subnets.template get<SubnetSubnetIdIndexTag>();
111 auto subnet_it = index.find(subnet_id);
112 if (subnet_it != index.cend()) {
113 return (*subnet_it);
114 }
115
116 // Subnet not found.
117 return (SubnetPtrType());
118 }
119
159 template<typename SubnetPtrType, typename SubnetCollectionType>
160 static SubnetPtrType getNextSubnet(const SubnetCollectionType& subnets,
161 const SubnetPtrType& first_subnet,
162 const SubnetID& current_subnet) {
163 // It is ok to have a shared network without any subnets, but in this
164 // case there is nothing else we can return but null pointer.
165 if (subnets.empty()) {
166 return (SubnetPtrType());
167 }
168
169 // Need to retrieve an iterator to the current subnet first. The
170 // subnet must exist in this container, thus we throw if the iterator
171 // is not found.
172 const auto& index = subnets.template get<SubnetSubnetIdIndexTag>();
173 auto subnet_id_it = index.find(current_subnet);
174 if (subnet_id_it == index.cend()) {
175 isc_throw(BadValue, "no such subnet " << current_subnet
176 << " within shared network");
177 }
178
179 // We need to transform this iterator (by subnet id) to a random access
180 // index iterator. Multi index container has a nice way of doing it.
181 auto subnet_it = subnets.template project<SubnetRandomAccessIndexTag>(subnet_id_it);
182
183 // Step to a next subnet within random access index.
184 if (++subnet_it == subnets.cend()) {
185 // If we reached the end of the container, start over from the
186 // beginning.
187 subnet_it = subnets.cbegin();
188 }
189
190 // Check if we have made a full circle. If we did, return a null pointer
191 // to indicate that there are no more subnets.
192 if ((*subnet_it)->getID() == first_subnet->getID()) {
193 return (SubnetPtrType());
194 }
195
196 // Got the next subnet, so return it.
197 return (*subnet_it);
198 }
199
224 template<typename SubnetPtrType, typename SubnetCollectionType>
225 static SubnetPtrType getPreferredSubnet(const SubnetCollectionType& subnets,
226 const SubnetPtrType& selected_subnet,
227 const Lease::Type& lease_type) {
228
229 auto preferred_subnet = selected_subnet;
230 for (auto s = subnets.begin(); s != subnets.end(); ++s) {
231 if (((*s)->getClientClass() == selected_subnet->getClientClass()) &&
232 ((*s)->getLastAllocatedTime(lease_type) >
233 selected_subnet->getLastAllocatedTime(lease_type))) {
234 preferred_subnet = (*s);
235 }
236 }
237
238 return (preferred_subnet);
239 }
240};
241
242} // end of anonymous namespace
243
244namespace isc {
245namespace dhcp {
246
249 return (shared_from_this());
250}
251
252void
254 Impl::add(subnets_, subnet);
255 // Associate the subnet with this network.
256 setSharedNetwork(subnet);
257}
258
259void
260SharedNetwork4::del(const SubnetID& subnet_id) {
261 Subnet4Ptr subnet = Impl::del<Subnet4Ptr>(subnets_, subnet_id);
262 clearSharedNetwork(subnet);
263}
264
265void
267 for (auto subnet = subnets_.cbegin(); subnet != subnets_.cend(); ++subnet) {
268 clearSharedNetwork(*subnet);
269 }
270 subnets_.clear();
271}
272
274SharedNetwork4::getSubnet(const SubnetID& subnet_id) const {
275 return (Impl::getSubnet<Subnet4Ptr>(subnets_, subnet_id));
276}
277
280 const SubnetID& current_subnet) const {
281 return (Impl::getNextSubnet(subnets_, first_subnet, current_subnet));
282}
283
285SharedNetwork4::getPreferredSubnet(const Subnet4Ptr& selected_subnet) const {
286 return (Impl::getPreferredSubnet<Subnet4Ptr>(subnets_, selected_subnet,
288}
289
293
294 // Set shared network name.
295 if (!name_.empty()) {
296 map->set("name", Element::create(name_));
297 }
298
300 for (auto subnet = subnets_.cbegin(); subnet != subnets_.cend(); ++subnet) {
301 subnet4->add((*subnet)->toElement());
302 }
303
304 map->set("subnet4", subnet4);
305
306 return (map);
307}
308
311 return (shared_from_this());
312}
313
314void
316 Impl::add(subnets_, subnet);
317 // Associate the subnet with this network.
318 setSharedNetwork(subnet);
319}
320
321void
322SharedNetwork6::del(const SubnetID& subnet_id) {
323 Subnet6Ptr subnet = Impl::del<Subnet6Ptr>(subnets_, subnet_id);
324 clearSharedNetwork(subnet);
325}
326
327void
329 for (auto subnet = subnets_.cbegin(); subnet != subnets_.cend(); ++subnet) {
330 clearSharedNetwork(*subnet);
331 }
332 subnets_.clear();
333}
335SharedNetwork6::getSubnet(const SubnetID& subnet_id) const {
336 return (Impl::getSubnet<Subnet6Ptr>(subnets_, subnet_id));
337}
338
341 const SubnetID& current_subnet) const {
342 return (Impl::getNextSubnet(subnets_, first_subnet, current_subnet));
343}
344
347 const Lease::Type& lease_type) const {
348 return (Impl::getPreferredSubnet(subnets_, selected_subnet, lease_type));
349}
350
354
355 // Set shared network name.
356 if (!name_.empty()) {
357 map->set("name", Element::create(name_));
358 }
359
361 for (auto subnet = subnets_.cbegin(); subnet != subnets_.cend(); ++subnet) {
362 subnet6->add((*subnet)->toElement());
363 }
364
365 map->set("subnet6", subnet6);
366
367 return (map);
368}
369
370} // end of namespace isc::dhcp
371} // 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:223
static ElementPtr createList(const Position &pos=ZERO_POSITION())
Creates an empty ListElement type ElementPtr.
Definition: data.cc:263
void setSharedNetwork(const SubnetPtr &subnet)
Associates a subnet with this network.
void clearSharedNetwork(const SubnetPtr &subnet)
Removes association of a subnet with a network.
Exception thrown upon attempt to add subnet with an ID that belongs to the subnet that already exists...
Definition: subnet_id.h:34
virtual data::ElementPtr toElement() const
Unparses network object.
Definition: network.cc:192
virtual data::ElementPtr toElement() const
Unparses network object.
Definition: network.cc:220
virtual NetworkPtr sharedFromThis()
Returns shared pointer to this network.
Subnet4Ptr getNextSubnet(const Subnet4Ptr &first_subnet, const SubnetID &current_subnet) const
Retrieves next available IPv4 subnet within shared network.
Subnet4Ptr getPreferredSubnet(const Subnet4Ptr &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.
Subnet6Ptr getNextSubnet(const Subnet6Ptr &first_subnet, const SubnetID &current_subnet) const
Retrieves next available IPv6 subnet within shared network.
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.
virtual NetworkPtr sharedFromThis()
Returns shared pointer to this network.
virtual data::ElementPtr toElement() const
Unparses shared network object.
Subnet6Ptr getPreferredSubnet(const Subnet6Ptr &selected_subnet, const Lease::Type &lease_type) const
Attempts to find a subnet which is more likely to include available leases than selected subnet.
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:22
boost::shared_ptr< Subnet4 > Subnet4Ptr
A pointer to a Subnet4 object.
Definition: subnet.h:464
boost::shared_ptr< Subnet6 > Subnet6Ptr
A pointer to a Subnet6 object.
Definition: subnet.h:629
uint32_t SubnetID
Unique identifier for a subnet (both v4 and v6)
Definition: lease.h:24
boost::shared_ptr< Network > NetworkPtr
Pointer to the Network object.
Definition: network.h:360
Defines the logger used by the top-level component of kea-dhcp-ddns.
Type
Type of lease or pool.
Definition: lease.h:38
@ TYPE_V4
IPv4 lease.
Definition: lease.h:42