alloc_engine.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. // Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef ALLOC_ENGINE_H
  15. #define ALLOC_ENGINE_H
  16. #include <asiolink/io_address.h>
  17. #include <dhcp/duid.h>
  18. #include <dhcp/hwaddr.h>
  19. #include <dhcpsrv/subnet.h>
  20. #include <dhcpsrv/lease_mgr.h>
  21. #include <hooks/callout_handle.h>
  22. #include <boost/shared_ptr.hpp>
  23. #include <boost/noncopyable.hpp>
  24. namespace isc {
  25. namespace dhcp {
  26. /// An exception that is thrown when allocation module fails (e.g. due to
  27. /// lack of available addresses)
  28. class AllocFailed : public isc::Exception {
  29. public:
  30. /// @brief constructor
  31. ///
  32. /// @param file name of the file, where exception occurred
  33. /// @param line line of the file, where exception occurred
  34. /// @param what text description of the issue that caused exception
  35. AllocFailed(const char* file, size_t line, const char* what)
  36. : isc::Exception(file, line, what) {}
  37. };
  38. /// @brief DHCPv4 and DHCPv6 allocation engine
  39. ///
  40. /// This class represents DHCP allocation engine. It is responsible
  41. /// for picking subnets, choosing and allocating a lease, extending,
  42. /// renewing, releasing and possibly expiring leases.
  43. ///
  44. /// @todo: Does not handle out of leases well
  45. /// @todo: Does not handle out of allocation attempts well
  46. class AllocEngine : public boost::noncopyable {
  47. protected:
  48. /// @brief base class for all address/prefix allocation algorithms
  49. ///
  50. /// This is an abstract class that should not be used directly, but rather
  51. /// specialized implementations should be used instead.
  52. class Allocator {
  53. public:
  54. /// @brief picks one address out of available pools in a given subnet
  55. ///
  56. /// This method returns one address from the available pools in the
  57. /// specified subnet. It should not check if the address is used or
  58. /// reserved - AllocEngine will check that and will call pickAddress
  59. /// again if necessary. The number of times this method is called will
  60. /// increase as the number of available leases will decrease.
  61. ///
  62. /// @param subnet next address will be returned from pool of that subnet
  63. /// @param duid Client's DUID
  64. /// @param hint client's hint
  65. ///
  66. /// @return the next address
  67. virtual isc::asiolink::IOAddress
  68. pickAddress(const SubnetPtr& subnet, const DuidPtr& duid,
  69. const isc::asiolink::IOAddress& hint) = 0;
  70. /// @brief virtual destructor
  71. virtual ~Allocator() {
  72. }
  73. protected:
  74. };
  75. /// @brief Address/prefix allocator that iterates over all addresses
  76. ///
  77. /// This class implements iterative algorithm that returns all addresses in
  78. /// a pool iteratively, one after another. Once the last address is reached,
  79. /// it starts allocating from the beginning of the first pool (i.e. it loops
  80. /// over).
  81. class IterativeAllocator : public Allocator {
  82. public:
  83. /// @brief default constructor
  84. ///
  85. /// Does not do anything
  86. IterativeAllocator();
  87. /// @brief returns the next address from pools in a subnet
  88. ///
  89. /// @param subnet next address will be returned from pool of that subnet
  90. /// @param duid Client's DUID (ignored)
  91. /// @param hint client's hint (ignored)
  92. /// @return the next address
  93. virtual isc::asiolink::IOAddress
  94. pickAddress(const SubnetPtr& subnet,
  95. const DuidPtr& duid,
  96. const isc::asiolink::IOAddress& hint);
  97. private:
  98. /// @brief returns an address by one
  99. /// @param addr address to be increased
  100. /// @return address increased by one
  101. isc::asiolink::IOAddress increaseAddress(const isc::asiolink::IOAddress& addr);
  102. };
  103. /// @brief Address/prefix allocator that gets an address based on a hash
  104. ///
  105. /// @todo: This is a skeleton class for now and is missing implementation.
  106. class HashedAllocator : public Allocator {
  107. public:
  108. /// @brief default constructor (does nothing)
  109. HashedAllocator();
  110. /// @brief returns an address based on hash calculated from client's DUID.
  111. ///
  112. /// @todo: Implement this method
  113. ///
  114. /// @param subnet an address will be picked from pool of that subnet
  115. /// @param duid Client's DUID
  116. /// @param hint a hint (last address that was picked)
  117. /// @return selected address
  118. virtual isc::asiolink::IOAddress pickAddress(const SubnetPtr& subnet,
  119. const DuidPtr& duid,
  120. const isc::asiolink::IOAddress& hint);
  121. };
  122. /// @brief Random allocator that picks address randomly
  123. ///
  124. /// @todo: This is a skeleton class for now and is missing implementation.
  125. class RandomAllocator : public Allocator {
  126. public:
  127. /// @brief default constructor (does nothing)
  128. RandomAllocator();
  129. /// @brief returns an random address from pool of specified subnet
  130. ///
  131. /// @todo: Implement this method
  132. ///
  133. /// @param subnet an address will be picked from pool of that subnet
  134. /// @param duid Client's DUID (ignored)
  135. /// @param hint the last address that was picked (ignored)
  136. /// @return a random address from the pool
  137. virtual isc::asiolink::IOAddress
  138. pickAddress(const SubnetPtr& subnet, const DuidPtr& duid,
  139. const isc::asiolink::IOAddress& hint);
  140. };
  141. public:
  142. /// @brief specifies allocation type
  143. typedef enum {
  144. ALLOC_ITERATIVE, // iterative - one address after another
  145. ALLOC_HASHED, // hashed - client's DUID/client-id is hashed
  146. ALLOC_RANDOM // random - an address is randomly selected
  147. } AllocType;
  148. /// @brief Default constructor.
  149. ///
  150. /// Instantiates necessary services, required to run DHCPv6 server.
  151. /// In particular, creates IfaceMgr that will be responsible for
  152. /// network interaction. Will instantiate lease manager, and load
  153. /// old or create new DUID.
  154. ///
  155. /// @param engine_type selects allocation algorithm
  156. /// @param attempts number of attempts for each lease allocation before
  157. /// we give up (0 means unlimited)
  158. AllocEngine(AllocType engine_type, unsigned int attempts);
  159. /// @brief Allocates an IPv4 lease
  160. ///
  161. /// This method uses currently selected allocator to pick an address from
  162. /// specified subnet, creates a lease for that address and then inserts
  163. /// it into LeaseMgr (if this allocation is not fake).
  164. ///
  165. /// @param subnet subnet the allocation should come from
  166. /// @param clientid Client identifier
  167. /// @param hwaddr client's hardware address info
  168. /// @param hint a hint that the client provided
  169. /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
  170. /// an address for DISCOVER that is not really allocated (true)
  171. /// @return Allocated IPv4 lease (or NULL if allocation failed)
  172. Lease4Ptr
  173. allocateAddress4(const SubnetPtr& subnet,
  174. const ClientIdPtr& clientid,
  175. const HWAddrPtr& hwaddr,
  176. const isc::asiolink::IOAddress& hint,
  177. bool fake_allocation);
  178. /// @brief Renews a IPv4 lease
  179. ///
  180. /// Since both request and renew are implemented in DHCPv4 as the sending of
  181. /// a REQUEST packet, it is difficult to easily distinguish between those
  182. /// cases. Therefore renew for DHCPv4 is done in the allocation engine.
  183. /// This method is also used when client crashed/rebooted and tries
  184. /// to get a new lease. It thinks that it gets a new lease, but in fact
  185. /// we are only renewing the still valid lease for that client.
  186. ///
  187. /// @param subnet subnet the client is attached to
  188. /// @param clientid client identifier
  189. /// @param hwaddr client's hardware address
  190. /// @param lease lease to be renewed
  191. /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
  192. /// an address for DISCOVER that is not really allocated (true)
  193. Lease4Ptr
  194. renewLease4(const SubnetPtr& subnet,
  195. const ClientIdPtr& clientid,
  196. const HWAddrPtr& hwaddr,
  197. const Lease4Ptr& lease,
  198. bool fake_allocation /* = false */);
  199. /// @brief Allocates an IPv6 lease
  200. ///
  201. /// This method uses currently selected allocator to pick an address from
  202. /// specified subnet, creates a lease for that address and then inserts
  203. /// it into LeaseMgr (if this allocation is not fake).
  204. ///
  205. /// @param subnet subnet the allocation should come from
  206. /// @param duid Client's DUID
  207. /// @param iaid iaid field from the IA_NA container that client sent
  208. /// @param hint a hint that the client provided
  209. /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
  210. /// an address for SOLICIT that is not really allocated (true)
  211. /// @param callout_handle a callout handle (used in hooks). A lease callouts
  212. /// will be executed if this parameter is passed.
  213. ///
  214. /// @return Allocated IPv6 lease (or NULL if allocation failed)
  215. Lease6Ptr
  216. allocateAddress6(const Subnet6Ptr& subnet,
  217. const DuidPtr& duid,
  218. uint32_t iaid,
  219. const isc::asiolink::IOAddress& hint,
  220. bool fake_allocation,
  221. const isc::hooks::CalloutHandlePtr& callout_handle);
  222. /// @brief Destructor. Used during DHCPv6 service shutdown.
  223. virtual ~AllocEngine();
  224. private:
  225. /// @brief Creates a lease and inserts it in LeaseMgr if necessary
  226. ///
  227. /// Creates a lease based on specified parameters and tries to insert it
  228. /// into the database. That may fail in some cases, e.g. when there is another
  229. /// allocation process and we lost a race to a specific lease.
  230. ///
  231. /// @param subnet subnet the lease is allocated from
  232. /// @param clientid client identifier
  233. /// @param hwaddr client's hardware address
  234. /// @param addr an address that was selected and is confirmed to be available
  235. /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
  236. /// an address for DISCOVER that is not really allocated (true)
  237. /// @return allocated lease (or NULL in the unlikely case of the lease just
  238. /// becomed unavailable)
  239. Lease4Ptr createLease4(const SubnetPtr& subnet, const DuidPtr& clientid,
  240. const HWAddrPtr& hwaddr,
  241. const isc::asiolink::IOAddress& addr,
  242. bool fake_allocation = false);
  243. /// @brief creates a lease and inserts it in LeaseMgr if necessary
  244. ///
  245. /// Creates a lease based on specified parameters and tries to insert it
  246. /// into the database. That may fail in some cases, i.e. when there is another
  247. /// allocation process and we lost a race to a specific lease.
  248. ///
  249. /// @param subnet subnet the lease is allocated from
  250. /// @param duid client's DUID
  251. /// @param iaid IAID from the IA_NA container the client sent to us
  252. /// @param addr an address that was selected and is confirmed to be available
  253. /// @param callout_handle a callout handle (used in hooks). A lease callouts
  254. /// will be executed if this parameter is passed.
  255. /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
  256. /// an address for SOLICIT that is not really allocated (true)
  257. /// @return allocated lease (or NULL in the unlikely case of the lease just
  258. /// becomed unavailable)
  259. Lease6Ptr createLease6(const Subnet6Ptr& subnet, const DuidPtr& duid,
  260. uint32_t iaid, const isc::asiolink::IOAddress& addr,
  261. const isc::hooks::CalloutHandlePtr& callout_handle,
  262. bool fake_allocation = false);
  263. /// @brief Reuses expired IPv4 lease
  264. ///
  265. /// Updates existing expired lease with new information. Lease database
  266. /// is updated if this is real (i.e. REQUEST, fake_allocation = false), not
  267. /// dummy allocation request (i.e. DISCOVER, fake_allocation = true).
  268. ///
  269. /// @param expired old, expired lease
  270. /// @param subnet subnet the lease is allocated from
  271. /// @param clientid client identifier
  272. /// @param hwaddr client's hardware address
  273. /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
  274. /// an address for DISCOVER that is not really allocated (true)
  275. /// @return refreshed lease
  276. /// @throw BadValue if trying to recycle lease that is still valid
  277. Lease4Ptr reuseExpiredLease(Lease4Ptr& expired, const SubnetPtr& subnet,
  278. const ClientIdPtr& clientid,
  279. const HWAddrPtr& hwaddr,
  280. bool fake_allocation = false);
  281. /// @brief Reuses expired IPv6 lease
  282. ///
  283. /// Updates existing expired lease with new information. Lease database
  284. /// is updated if this is real (i.e. REQUEST, fake_allocation = false), not
  285. /// dummy allocation request (i.e. SOLICIT, fake_allocation = true).
  286. ///
  287. /// @param expired old, expired lease
  288. /// @param subnet subnet the lease is allocated from
  289. /// @param duid client's DUID
  290. /// @param iaid IAID from the IA_NA container the client sent to us
  291. /// @param callout_handle a callout handle (used in hooks). A lease callouts
  292. /// will be executed if this parameter is passed.
  293. /// @param fake_allocation is this real i.e. REQUEST (false) or just picking
  294. /// an address for SOLICIT that is not really allocated (true)
  295. /// @return refreshed lease
  296. /// @throw BadValue if trying to recycle lease that is still valid
  297. Lease6Ptr reuseExpiredLease(Lease6Ptr& expired, const Subnet6Ptr& subnet,
  298. const DuidPtr& duid, uint32_t iaid,
  299. const isc::hooks::CalloutHandlePtr& callout_handle,
  300. bool fake_allocation = false);
  301. /// @brief a pointer to currently used allocator
  302. boost::shared_ptr<Allocator> allocator_;
  303. /// @brief number of attempts before we give up lease allocation (0=unlimited)
  304. unsigned int attempts_;
  305. /// @brief hook name index (used in hooks callouts)
  306. int hook_index_lease6_select_;
  307. };
  308. }; // namespace isc::dhcp
  309. }; // namespace isc
  310. #endif // ALLOC_ENGINE_H