summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcpsrv/allocator.h
blob: 66f2302dbc0fd5a543db92e215c949ddfe1ea0c6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
// Copyright (C) 2022-2023 Internet Systems Consortium, Inc. ("ISC")
//
// 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 ALLOCATOR_H
#define ALLOCATOR_H

#include <asiolink/io_address.h>
#include <dhcp/classify.h>
#include <dhcp/duid.h>
#include <exceptions/exceptions.h>
#include <dhcpsrv/lease.h>
#include <dhcpsrv/subnet_id.h>
#include <dhcpsrv/pool.h>
#include <util/multi_threading_mgr.h>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <mutex>

namespace isc {
namespace dhcp {

/// @brief Forward declaration of a @c Subnet.
///
/// We don't include the subnet header because it would cause a
/// circular dependency.
class Subnet;

/// @brief Weak pointer to the @c Subnet.
typedef boost::weak_ptr<Subnet> WeakSubnetPtr;

/// An exception that is thrown when allocation module fails (e.g. due to
/// lack of available addresses)
class AllocFailed : public Exception {
public:

    /// @brief Constructor
    ///
    /// @param file name of the file, where exception occurred
    /// @param line line of the file, where exception occurred
    /// @param what text description of the issue that caused exception
    AllocFailed(const char* file, size_t line, const char* what)
        : Exception(file, line, what) {}
};

/// @brief Base class for all address/prefix allocation algorithms.
///
/// This is an abstract class that should not be used directly, but rather
/// specialized implementations should be used instead.
///
/// This class holds a weak pointer to the subnet owning it because
/// it must not exist without the subnet. Also, it can't hold a shared
/// pointer to the subnet because it would cause a circular dependency
/// between the two.
class Allocator {
public:

    /// @brief Type of preferred PD-pool prefix length selection criteria
    enum PrefixLenMatchType {
        PREFIX_LEN_EQUAL,      // select PD-pools with specific prefix length
        PREFIX_LEN_LOWER,      // select PD-pools with lower prefix length
        PREFIX_LEN_HIGHER      // select PD-pools with higher prefix length
    };

    /// @brief Constructor
    ///
    /// Specifies which type of leases this allocator will assign.
    ///
    /// @param type specifies pool type (addresses, temporary addresses
    /// or prefixes).
    /// @param subnet weak pointer to the subnet owning the allocator.
    Allocator(Lease::Type type, const WeakSubnetPtr& subnet);

    /// @brief Virtual destructor.
    ///
    /// Removes all LeaseMgr callbacks it installed.
    virtual ~Allocator();

    /// @brief Returns allocator type string.
    ///
    /// @return allocator-specific type string.
    virtual std::string getType() const = 0;

    /// @brief Picks an address.
    ///
    /// This method returns one address from the available pools in the
    /// specified subnet. It should not check if the address is used or
    /// reserved - AllocEngine will check that and will call pickAddress
    /// again if necessary. The number of times this method is called will
    /// increase as the number of available leases will decrease.
    ///
    /// Pools which are not allowed for client classes are skipped.
    ///
    /// @param client_classes list of classes client belongs to.
    /// @param duid Client's DUID.
    /// @param hint Client's hint.
    ///
    /// @return the next address.
    virtual isc::asiolink::IOAddress
    pickAddress(const ClientClasses& client_classes,
                const IdentifierBaseTypePtr& duid,
                const asiolink::IOAddress& hint) {
        util::MultiThreadingLock lock(mutex_);
        return (pickAddressInternal(client_classes, duid, hint));
    }

    /// @brief Picks a delegated prefix.
    ///
    /// This method returns one prefix from the available pools in the
    /// specified subnet. It should not check if the prefix is used or
    /// reserved - AllocEngine will check that and will call pickPrefix
    /// again if necessary. The number of times this method is called will
    /// increase as the number of available leases will decrease.
    ///
    /// Pools which are not allowed for client classes are skipped.
    ///
    /// @param client_classes list of classes client belongs to.
    /// @param pool the selected pool satisfying all required conditions.
    /// @param duid Client's DUID.
    /// @param prefix_length_match type which indicates the selection criteria
    ///        for the pools relative to the provided hint prefix length.
    /// @param hint Client's hint.
    /// @param hint_prefix_length the hint prefix length that the client
    ///        provided. The 0 value means that there is no hint and that any
    ///        pool will suffice.
    ///
    /// @return the next prefix.
    virtual isc::asiolink::IOAddress
    pickPrefix(const ClientClasses& client_classes,
               Pool6Ptr& pool,
               const IdentifierBaseTypePtr& duid,
               PrefixLenMatchType prefix_length_match,
               const asiolink::IOAddress& hint,
               uint8_t hint_prefix_length) {
        util::MultiThreadingLock lock(mutex_);
        return (pickPrefixInternal(client_classes, pool, duid,
                                   prefix_length_match, hint,
                                   hint_prefix_length));
    }

    /// @brief Check if the pool matches the selection criteria relative to the
    /// provided hint prefix length.
    ///
    /// @param prefix_length_match type which indicates the selection criteria
    ///        for the pools relative to the provided hint prefix length.
    /// @param pool the pool checked for restricted delegated prefix length
    ///        value.
    /// @param hint_prefix_length The hint prefix length that the client
    ///        provided. The 0 value means that there is no hint and that any
    ///        pool will suffice.
    static bool isValidPrefixPool(Allocator::PrefixLenMatchType prefix_length_match,
                                  PoolPtr pool, uint8_t hint_prefix_length);

    /// @brief Performs allocator initialization after server's reconfiguration.
    ///
    /// Some allocators install callbacks in the lease manager to keep track of
    /// the lease allocations. These callbacks may only be installed when the
    /// lease manager instance is available (i.e., when the server finishes the
    /// reconfiguration). Such callbacks can be installed in this function.
    ///
    /// In this function, the allocators can also re-build their allocation states.
    void initAfterConfigure();

protected:

    /// @brief Allocator-specific initialization function.
    ///
    /// It is called by the @c initAfterConfigure and can be overridden in the
    /// derived allocators.
    virtual void initAfterConfigureInternal() {};

private:

    /// @brief Picks an address.
    ///
    /// Internal thread-unsafe implementation of the @c pickAddress.
    /// Derived classes must provide their specific implementations of
    /// this function.
    ///
    /// @param client_classes list of classes client belongs to
    /// @param duid Client's DUID
    /// @param hint Client's hint
    ///
    /// @return the next address.
    virtual isc::asiolink::IOAddress
    pickAddressInternal(const ClientClasses& client_classes,
                        const IdentifierBaseTypePtr& duid,
                        const isc::asiolink::IOAddress& hint) = 0;

    /// @brief Picks a delegated prefix.
    ///
    /// Internal thread-unsafe implementation of the @c pickPrefix.
    /// Derived classes must provide their specific implementations of
    /// this function.
    ///
    /// @param client_classes list of classes client belongs to.
    /// @param pool the selected pool satisfying all required conditions.
    /// @param duid Client's DUID.
    /// @param prefix_length_match type which indicates the selection criteria
    ///        for the pools relative to the provided hint prefix length.
    /// @param hint Client's hint.
    /// @param hint_prefix_length the hint prefix length that the client
    ///        provided. The 0 value means that there is no hint and that any
    ///        pool will suffice.
    ///
    /// @return the next prefix.
    virtual isc::asiolink::IOAddress
    pickPrefixInternal(const ClientClasses& client_classes,
                       Pool6Ptr& pool,
                       const IdentifierBaseTypePtr& duid,
                       PrefixLenMatchType prefix_length_match,
                       const isc::asiolink::IOAddress& hint,
                       uint8_t hint_prefix_length) = 0;

protected:

    /// @brief Indicates if the allocator has been initialized.
    ///
    /// It is set to true when @c initAfterConfigure has been called.
    /// It prevents initializing the allocator several times.
    bool inited_;

    /// @brief Defines pool type allocation
    Lease::Type pool_type_;

    /// @brief ID of a subnet to which the allocator belongs.
    SubnetID subnet_id_;

    /// @brief Weak pointer to the subnet owning the allocator.
    WeakSubnetPtr subnet_;

    /// @brief The mutex to protect the allocated lease.
    std::mutex mutex_;
};

/// Defines a pointer to an allocator.
typedef boost::shared_ptr<Allocator> AllocatorPtr;

} // end of namespace isc::dhcp
} // end of namespace isc

#endif // ALLOCATOR_H