shared_network.h 17.9 KB
Newer Older
1
// Copyright (C) 2017-2019 Internet Systems Consortium, Inc. ("ISC")
2
3
4
5
6
7
8
9
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef SHARED_NETWORK_H
#define SHARED_NETWORK_H

10
#include <asiolink/io_address.h>
11
#include <cc/data.h>
12
13
14
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/subnet_id.h>
#include <boost/enable_shared_from_this.hpp>
15
#include <boost/multi_index/mem_fun.hpp>
16
#include <boost/multi_index/hashed_index.hpp>
17
18
19
20
#include <boost/multi_index/indexed_by.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index_container.hpp>
21
#include <boost/shared_ptr.hpp>
22
#include <string>
23
24
25
26

namespace isc {
namespace dhcp {

27
28
29
/// @brief A tag for accessing random access index.
struct SharedNetworkRandomAccessIndexTag { };

30
31
32
/// @brief A tag for accessing index by id.
struct SharedNetworkIdIndexTag { };

33
34
35
/// @brief A tag for accessing index by shared network name.
struct SharedNetworkNameIndexTag { };

36
37
38
/// @brief A tag for accessing index by server identifier.
struct SharedNetworkServerIdIndexTag { };

39
40
41
42
/// @brief Tag for the index for searching by shared network modification
/// time.
struct SharedNetworkModificationTimeIndexTag { };

43
44
45
46
47
class SharedNetwork4;

/// @brief Pointer to @ref SharedNetwork4 object.
typedef boost::shared_ptr<SharedNetwork4> SharedNetwork4Ptr;

48
49
/// @brief Shared network holding IPv4 subnets.
///
50
/// Specialization of the @ref Network4 class for IPv4 shared networks.
51
52
class SharedNetwork4 : public virtual Network4,
                       public boost::enable_shared_from_this<SharedNetwork4> {
53
54
public:

55
56
57
    /// @brief Constructor.
    ///
    /// Sets name of the shared network.
58
59
    ///
    /// @param name Name of the shared network.
60
    explicit SharedNetwork4(const std::string& name)
61
        : name_(name), subnets_() {
62
63
    }

64
65
66
67
68
69
70
71
72
73
74
75
    /// @brief Factory function creating an instance of the @c SharedNetwork4.
    ///
    /// This function should be used to create an instance of the shared
    /// network within a hooks library in cases when the library may be
    /// unloaded before the object is destroyed. This ensures that the
    /// ownership of the object by the Kea process is retained.
    ///
    /// @param name Name of the shared network.
    ///
    /// @return Pointer to the @c SharedNetwork4 instance.
    static SharedNetwork4Ptr create(const std::string& name);

76
77
78
79
80
81
82
83
84
85
86
87
    /// @brief Returns a name of the shared network.
    std::string getName() const {
        return (name_);
    }

    /// @brief Sets new name for the shared network.
    ///
    /// @param name New name for the shared network.
    void setName(const std::string& name) {
        name_ = name;
    }

88
89
90
91
92
93
94
95
96
97
98
    /// @brief Adds IPv4 subnet to a shared network.
    ///
    /// @param subnet Pointer to a subnet being added to this shared network.
    ///
    /// @throw isc::BadValue if subnet is null.
    /// @throw isc::DuplicateSubnetID if a subnet with the given subnet id
    /// already exists in this shared network.
    /// @throw InvalidOperation if a subnet is already associated with some
    /// shared network.
    void add(const Subnet4Ptr& subnet);

99
100
101
102
103
104
105
106
107
108
109
110
111
    /// @brief Replaces IPv4 subnet in a shared network.
    ///
    /// This method replaces a subnet by another subnet with the same ID.
    /// The prefix should be the same too.
    ///
    /// @param subnet Pointer to a subnet replacing the subnet with the same ID
    /// in this shared network.
    /// @throw isc::BadValue if subnet is null.
    /// @throw InvalidOperation if a subnet is already associated with some
    /// shared network.
    /// @return true if the operation succeeded, false otherwise.
    bool replace(const Subnet4Ptr& subnet);

112
113
114
115
116
117
118
    /// @brief Removes subnet from a shared network.
    ///
    /// @param subnet_id Identifier of a subnet to be removed.
    ///
    /// @throw BadValue When specified subnet doesn't exist.
    void del(const SubnetID& subnet_id);

119
120
121
    /// @brief Removes all subnets from a shared network.
    void delAll();

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
    /// @brief Returns a pointer to the collection of subnets within this
    /// shared network.
    const Subnet4Collection* getAllSubnets() const {
        return (&subnets_);
    }

    /// @brief Returns a subnet for a specified subnet id.
    ///
    /// @param subnet_id Subnet identifier.
    ///
    /// @return Shared pointer to a subnet using this id or null pointer
    /// if such subnet doesn't exist within shared network.
    Subnet4Ptr getSubnet(const SubnetID& subnet_id) const;

    /// @brief Retrieves next available IPv4 subnet within shared network.
    ///
Francis Dupont's avatar
Francis Dupont committed
138
    /// See documentation for @ref SharedNetwork4::getNextSubnet.
139
140
141
142
    ///
    /// @param first_subnet Pointer to a subnet from which the caller is
    /// iterating over subnets within shared network. This is typically a
    /// subnet selected during "subnet selection" step.
143
    /// @param current_subnet Identifier of a subnet for which next subnet is
144
145
146
147
148
149
150
    /// to be found.
    ///
    /// @return Pointer to next subnet or null pointer if no more subnets found.
    ///
    /// @throw isc::BadValue if invalid arguments specified, e.g. unable to
    /// find first or current subnet within shared network.
    Subnet4Ptr getNextSubnet(const Subnet4Ptr& first_subnet,
151
                             const SubnetID& current_subnet) const;
152

153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
    /// @brief Attempts to find a subnet which is more likely to include available
    /// leases than selected subnet.
    ///
    /// When allocating unreserved leases from a shared network it is important to
    /// remember from which subnet within the shared network we have been recently
    /// handing out leases. The allocation engine can use that information to start
    /// trying allocation of the leases from that subnet rather than from the default
    /// subnet selected for this client. Starting from the default subnet causes a
    /// risk of having to walk over many subnets with exhausted address pools before
    /// getting to the subnet with available leases. This method attempts to find
    /// such subnet by inspecting "last allocation" timestamps. The one with most
    /// recent timestamp is selected.
    ///
    /// The preferred subnet must also fulfil the condition of equal client classes
    /// with the @c selected_subnet.
    ///
169
170
171
    /// @todo Need extensions to this logic when we support more than one client
    /// class for a subnet.
    ///
172
173
174
175
176
177
    /// @param selected_subnet Pointer to a currently selected subnet.
    ///
    /// @return Pointer to a preferred subnet. It may be the same as @c selected_subnet
    /// if no better subnet was found.
    Subnet4Ptr getPreferredSubnet(const Subnet4Ptr& selected_subnet) const;

178
179
180
181
182
    /// @brief Checks if the shared network includes a subnet with
    /// the match client ID flag set to true.
    ///
    /// @param first_subnet Pointer to the subnet from which iteration starts.
    /// @param client_classes List of classes that the client belongs to.
183
    /// @return true if the shared network includes at least one subnet
184
185
186
187
188
189
190
191
192
193
194
195
196
    /// guarded by a given class with the match client ID flag set to true.
    /// False otherwise.
    static
    bool subnetsIncludeMatchClientId(const Subnet4Ptr& first_subnet,
                                     const ClientClasses& client_classes);

    /// @brief Check if the shared network includes a subnet with
    /// not global host reservation mode.
    ///
    /// @param [out] bad_subnet First subnet which has not a global host
    /// reservation mode.
    void subnetsAllHRGlobal(Subnet4Ptr& bad_subnet) const;

197
198
199
200
201
    /// @brief Unparses shared network object.
    ///
    /// @return A pointer to unparsed shared network configuration.
    virtual data::ElementPtr toElement() const;

202
203
private:

204
205
206
    /// @brief Holds a name of a shared network.
    std::string name_;

207
208
209
210
    /// @brief Collection of IPv4 subnets within shared network.
    Subnet4Collection subnets_;
};

211
212
213
214
215
216
217
218
219
220
221
222
223
224
/// @brief Multi index container holding shared networks.
///
/// This is multi index container can hold pointers to @ref SharedNetwork4
/// objects. It provides indexes for shared network lookups using properties
/// such as shared network's name.
typedef boost::multi_index_container<
    // Multi index container holds pointers to the shared networks.
    SharedNetwork4Ptr,
    boost::multi_index::indexed_by<
        // First is the random access index allowing for accessing objects
        // just like we'd do with vector.
        boost::multi_index::random_access<
            boost::multi_index::tag<SharedNetworkRandomAccessIndexTag>
        >,
225
226
227
228
229
230
231
        // Second index allows for access by shared network id.
        boost::multi_index::hashed_non_unique<
            boost::multi_index::tag<SharedNetworkIdIndexTag>,
            boost::multi_index::const_mem_fun<data::StampedElement, uint64_t,
                                              &data::StampedElement::getId>
        >,
        // Third index allows for access by shared network's name.
232
233
234
235
        boost::multi_index::ordered_unique<
            boost::multi_index::tag<SharedNetworkNameIndexTag>,
            boost::multi_index::const_mem_fun<SharedNetwork4, std::string,
                                              &SharedNetwork4::getName>
236
        >,
237
        // Fourth index allows for access by server identifier specified for the
238
239
240
241
242
        // network.
        boost::multi_index::ordered_non_unique<
            boost::multi_index::tag<SharedNetworkServerIdIndexTag>,
            boost::multi_index::const_mem_fun<Network4, asiolink::IOAddress,
                                              &Network4::getServerId>
243
        >,
244
        // Fifth index allows for searching using subnet modification time.
245
246
247
248
249
        boost::multi_index::ordered_non_unique<
            boost::multi_index::tag<SharedNetworkModificationTimeIndexTag>,
            boost::multi_index::const_mem_fun<data::StampedElement,
                                              boost::posix_time::ptime,
                                              &data::StampedElement::getModificationTime>
250
251
252
        >
    >
> SharedNetwork4Collection;
253

254
255
256
257
258
class SharedNetwork6;

/// @brief Pointer to @ref SharedNetwork6 object.
typedef boost::shared_ptr<SharedNetwork6> SharedNetwork6Ptr;

259
260
/// @brief Shared network holding IPv6 subnets.
///
261
/// Specialization of the @ref Network6 class for IPv6 shared networks.
262
263
class SharedNetwork6 : public virtual Network6,
                       public boost::enable_shared_from_this<SharedNetwork6> {
264
265
public:

266
267
268
269
    /// @brief Constructor.
    ///
    /// Sets name of the shared network.
    explicit SharedNetwork6(const std::string& name)
270
        : name_(name), subnets_() {
271
272
    }

273
274
275
276
277
278
279
280
281
282
283
284
    /// @brief Factory function creating an instance of the @c SharedNetwork6.
    ///
    /// This function should be used to create an instance of the shared
    /// network within a hooks library in cases when the library may be
    /// unloaded before the object is destroyed. This ensures that the
    /// ownership of the object by the Kea process is retained.
    ///
    /// @param name Name of the shared network.
    ///
    /// @return Pointer to the @c SharedNetwork6 instance.
    static SharedNetwork6Ptr create(const std::string& name);

285
286
287
288
289
290
291
292
293
294
295
296
    /// @brief Returns a name of the shared network.
    std::string getName() const {
        return (name_);
    }

    /// @brief Sets new name for the shared network.
    ///
    /// @param name New name for the shared network.
    void setName(const std::string& name) {
        name_ = name;
    }

297
298
299
300
301
302
303
304
305
306
307
    /// @brief Adds IPv6 subnet to a shared network.
    ///
    /// @param subnet Pointer to a subnet being added to this shared network.
    ///
    /// @throw isc::BadValue if subnet is null.
    /// @throw isc::DuplicateSubnetID if a subnet with the given subnet id
    /// already exists in this shared network.
    /// @throw InvalidOperation if a subnet is already associated with some
    /// shared network.
    void add(const Subnet6Ptr& subnet);

308
309
310
311
312
313
314
315
316
317
318
319
320
    /// @brief Replaces IPv6 subnet in a shared network.
    ///
    /// This method replaces a subnet by another subnet with the same ID.
    /// The prefix should be the same too.
    ///
    /// @param subnet Pointer to a subnet replacing the subnet with the same ID
    /// in this shared network.
    /// @throw isc::BadValue if subnet is null.
    /// @throw InvalidOperation if a subnet is already associated with some
    /// shared network.
    /// @return true if the operation succeeded, false otherwise.
    bool replace(const Subnet6Ptr& subnet);

321
322
323
324
325
326
327
    /// @brief Removes subnet from a shared network.
    ///
    /// @param subnet_id Identifier of a subnet to be removed.
    ///
    /// @throw BadValue When specified subnet doesn't exist.
    void del(const SubnetID& subnet_id);

328
329
330
    /// @brief Removes all subnets from a shared network.
    void delAll();

331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
    /// @brief Returns a pointer to the collection of subnets within this
    /// shared network.
    const Subnet6Collection* getAllSubnets() const {
        return (&subnets_);
    }

    /// @brief Returns a subnet for a specified subnet id.
    ///
    /// @param subnet_id Subnet identifier.
    ///
    /// @return Shared pointer to a subnet using this id or null pointer
    /// if such subnet doesn't exist within shared network.
    Subnet6Ptr getSubnet(const SubnetID& subnet_id) const;

    /// @brief Retrieves next available IPv6 subnet within shared network.
    ///
Francis Dupont's avatar
Francis Dupont committed
347
    /// See documentation for @ref SharedNetwork6::getNextSubnet.
348
349
350
351
    ///
    /// @param first_subnet Pointer to a subnet from which the caller is
    /// iterating over subnets within shared network. This is typically a
    /// subnet selected during "subnet selection" step.
352
    /// @param current_subnet Identifier of a subnet for which next subnet is
353
354
355
356
357
358
359
    /// to be found.
    ///
    /// @return Pointer to next subnet or null pointer if no more subnets found.
    ///
    /// @throw isc::BadValue if invalid arguments specified, e.g. unable to
    /// find first or current subnet within shared network.
    Subnet6Ptr getNextSubnet(const Subnet6Ptr& first_subnet,
360
                             const SubnetID& current_subnet) const;
361

362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
    /// @brief Attempts to find a subnet which is more likely to include available
    /// leases than selected subnet.
    ///
    /// When allocating unreserved leases from a shared network it is important to
    /// remember from which subnet within the shared network we have been recently
    /// handing out leases. The allocation engine can use that information to start
    /// trying allocation of the leases from that subnet rather than from the default
    /// subnet selected for this client. Starting from the default subnet causes a
    /// risk of having to walk over many subnets with exhausted address pools before
    /// getting to the subnet with available leases. This method attempts to find
    /// such subnet by inspecting "last allocation" timestamps. The one with most
    /// recent timestamp is selected.
    ///
    /// The preferred subnet must also fulfil the condition of equal client classes
    /// with the @c selected_subnet.
    ///
    /// @param selected_subnet Pointer to a currently selected subnet.
    /// @param lease_type Type of the lease for which preferred subnet should be
    /// returned.
    ///
    /// @return Pointer to a preferred subnet. It may be the same as @c selected_subnet
    /// if no better subnet was found.
    Subnet6Ptr getPreferredSubnet(const Subnet6Ptr& selected_subnet,
                                  const Lease::Type& lease_type) const;

387
388
389
390
391
392
393
    /// @brief Check if the shared network includes a subnet with
    /// not global host reservation mode.
    ///
    /// @param [out] bad_subnet First subnet which has not a global host
    /// reservation mode.
    void subnetsAllHRGlobal(Subnet6Ptr& bad_subnet) const;

394
395
396
397
398
    /// @brief Unparses shared network object.
    ///
    /// @return A pointer to unparsed shared network configuration.
    virtual data::ElementPtr toElement() const;

399
400
private:

401
402
403
    /// @brief Holds a name of a shared network.
    std::string name_;

404
405
406
407
    /// @brief Collection of IPv6 subnets within shared network.
    Subnet6Collection subnets_;
};

408
409
410
411
412
413
414
415
416
417
418
419
420
421
/// @brief Multi index container holding shared networks.
///
/// This is multi index container can hold pointers to @ref SharedNetwork6
/// objects. It provides indexes for shared network lookups using properties
/// such as shared network's name.
typedef boost::multi_index_container<
    // Multi index container holds pointers to the shared networks.
    SharedNetwork6Ptr,
    boost::multi_index::indexed_by<
        // First is the random access index allowing for accessing objects
        // just like we'd do with vector.
        boost::multi_index::random_access<
            boost::multi_index::tag<SharedNetworkRandomAccessIndexTag>
        >,
422
423
424
425
426
427
428
        // Second index allows for access by shared network id.
        boost::multi_index::hashed_non_unique<
            boost::multi_index::tag<SharedNetworkIdIndexTag>,
            boost::multi_index::const_mem_fun<data::StampedElement, uint64_t,
                                              &data::StampedElement::getId>
        >,
        // Third index allows for access by shared network's name.
429
430
431
432
        boost::multi_index::ordered_unique<
            boost::multi_index::tag<SharedNetworkNameIndexTag>,
            boost::multi_index::const_mem_fun<SharedNetwork6, std::string,
                                              &SharedNetwork6::getName>
433
        >,
434
        // Fourth index allows for searching using subnet modification time.
435
436
437
438
439
        boost::multi_index::ordered_non_unique<
            boost::multi_index::tag<SharedNetworkModificationTimeIndexTag>,
            boost::multi_index::const_mem_fun<data::StampedElement,
                                              boost::posix_time::ptime,
                                              &data::StampedElement::getModificationTime>
440
441
442
        >
    >
> SharedNetwork6Collection;
443

444
445
446
447
} // end of namespace isc::dhcp
} // end of namespace isc

#endif // SHARED_NETWORK_H