alloc_engine_utils.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. // Copyright (C) 2012-2015 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. #include <config.h>
  15. #include <dhcp/duid.h>
  16. #include <dhcp/dhcp4.h>
  17. #include <dhcp/dhcp6.h>
  18. #include <dhcpsrv/host_mgr.h>
  19. #include <dhcpsrv/lease_mgr.h>
  20. #include <dhcpsrv/memfile_lease_mgr.h>
  21. #include <dhcpsrv/tests/test_utils.h>
  22. #include <dhcpsrv/tests/alloc_engine_utils.h>
  23. #include <hooks/hooks_manager.h>
  24. #include <boost/shared_ptr.hpp>
  25. #include <boost/scoped_ptr.hpp>
  26. #include <iostream>
  27. #include <sstream>
  28. #include <algorithm>
  29. #include <set>
  30. #include <time.h>
  31. using namespace std;
  32. using namespace isc::hooks;
  33. using namespace isc::asiolink;
  34. namespace isc {
  35. namespace dhcp {
  36. namespace test {
  37. AllocEngine6Test::AllocEngine6Test() {
  38. CfgMgr::instance().clear();
  39. duid_ = DuidPtr(new DUID(std::vector<uint8_t>(8, 0x42)));
  40. iaid_ = 42;
  41. // Initialize a subnet and short address pool.
  42. initSubnet(IOAddress("2001:db8:1::"),
  43. IOAddress("2001:db8:1::10"),
  44. IOAddress("2001:db8:1::20"));
  45. initFqdn("", false, false);
  46. factory_.create("type=memfile universe=6 persist=false");
  47. }
  48. void
  49. AllocEngine6Test::initSubnet(const asiolink::IOAddress& subnet,
  50. const asiolink::IOAddress& pool_start,
  51. const asiolink::IOAddress& pool_end) {
  52. CfgMgr& cfg_mgr = CfgMgr::instance();
  53. subnet_ = Subnet6Ptr(new Subnet6(subnet, 56, 1, 2, 3, 4));
  54. pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, pool_start, pool_end));
  55. subnet_->addPool(pool_);
  56. pd_pool_ = Pool6Ptr(new Pool6(Lease::TYPE_PD, subnet, 56, 64));
  57. subnet_->addPool(pd_pool_);
  58. cfg_mgr.getStagingCfg()->getCfgSubnets6()->add(subnet_);
  59. cfg_mgr.commit();
  60. }
  61. Lease6Collection
  62. AllocEngine6Test::allocateTest(AllocEngine& engine, const Pool6Ptr& pool,
  63. const asiolink::IOAddress& hint, bool fake,
  64. bool in_pool) {
  65. Lease::Type type = pool->getType();
  66. uint8_t expected_len = pool->getLength();
  67. AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, hint, type,
  68. false, false, "", fake);
  69. Lease6Collection leases;
  70. EXPECT_NO_THROW(leases = engine.allocateLeases6(ctx));
  71. for (Lease6Collection::iterator it = leases.begin(); it != leases.end(); ++it) {
  72. // Do all checks on the lease
  73. checkLease6(*it, type, expected_len, in_pool, in_pool);
  74. // Check that the lease is indeed in LeaseMgr
  75. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(type,
  76. (*it)->addr_);
  77. if (!fake) {
  78. // This is a real (REQUEST) allocation, the lease must be in the DB
  79. EXPECT_TRUE(from_mgr) << "Lease " << from_mgr->addr_.toText()
  80. << " returned by allocateLeases6(), "
  81. << "but was not present in LeaseMgr";
  82. if (!from_mgr) {
  83. return (leases);
  84. }
  85. // Now check that the lease in LeaseMgr has the same parameters
  86. detailCompareLease(*it, from_mgr);
  87. } else {
  88. // This is a fake (SOLICIT) allocation, the lease must not be in DB
  89. EXPECT_FALSE(from_mgr) << "Lease " << from_mgr->addr_.toText()
  90. << " returned by allocateLeases6(), "
  91. << "was present in LeaseMgr (expected to be"
  92. << " not present)";
  93. if (from_mgr) {
  94. return (leases);
  95. }
  96. }
  97. }
  98. return (leases);
  99. }
  100. Lease6Ptr
  101. AllocEngine6Test::simpleAlloc6Test(const Pool6Ptr& pool, const IOAddress& hint,
  102. bool fake, bool in_pool) {
  103. Lease::Type type = pool->getType();
  104. uint8_t expected_len = pool->getLength();
  105. boost::scoped_ptr<AllocEngine> engine;
  106. EXPECT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE,
  107. 100)));
  108. // We can't use ASSERT macros in non-void methods
  109. EXPECT_TRUE(engine);
  110. if (!engine) {
  111. return (Lease6Ptr());
  112. }
  113. Lease6Ptr lease;
  114. AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, hint, type,
  115. false, false, "", fake);
  116. EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
  117. // Check that we got a lease
  118. EXPECT_TRUE(lease);
  119. if (!lease) {
  120. return (Lease6Ptr());
  121. }
  122. // Do all checks on the lease
  123. checkLease6(lease, type, expected_len, in_pool, in_pool);
  124. // Check that the lease is indeed in LeaseMgr
  125. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(type, lease->addr_);
  126. if (!fake) {
  127. // This is a real (REQUEST) allocation, the lease must be in the DB
  128. EXPECT_TRUE(from_mgr);
  129. if (!from_mgr) {
  130. return (Lease6Ptr());
  131. }
  132. // Now check that the lease in LeaseMgr has the same parameters
  133. detailCompareLease(lease, from_mgr);
  134. } else {
  135. // This is a fake (SOLICIT) allocation, the lease must not be in DB
  136. EXPECT_FALSE(from_mgr);
  137. if (from_mgr) {
  138. return (Lease6Ptr());
  139. }
  140. }
  141. return (lease);
  142. }
  143. Lease6Collection
  144. AllocEngine6Test::renewTest(AllocEngine& engine, const Pool6Ptr& pool,
  145. AllocEngine::HintContainer& hints,
  146. bool allow_new_leases_in_renewal,
  147. bool in_pool) {
  148. Lease::Type type = pool->getType();
  149. uint8_t expected_len = pool->getLength();
  150. AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, IOAddress("::"),
  151. type, false, false, "", false);
  152. ctx.hints_ = hints;
  153. ctx.query_.reset(new Pkt6(DHCPV6_RENEW, 123));
  154. ctx.allow_new_leases_in_renewals_ = allow_new_leases_in_renewal;
  155. Lease6Collection leases = engine.renewLeases6(ctx);
  156. for (Lease6Collection::iterator it = leases.begin(); it != leases.end(); ++it) {
  157. // Do all checks on the lease
  158. checkLease6(*it, type, expected_len, in_pool, in_pool);
  159. // Check that the lease is indeed in LeaseMgr
  160. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(type,
  161. (*it)->addr_);
  162. // This is a real (REQUEST) allocation, the lease must be in the DB
  163. EXPECT_TRUE(from_mgr) << "Lease " << from_mgr->addr_.toText()
  164. << " returned by allocateLeases6(), "
  165. << "but was not present in LeaseMgr";
  166. if (!from_mgr) {
  167. return (leases);
  168. }
  169. // Now check that the lease in LeaseMgr has the same parameters
  170. detailCompareLease(*it, from_mgr);
  171. }
  172. return (leases);
  173. }
  174. void
  175. AllocEngine6Test::allocWithUsedHintTest(Lease::Type type, IOAddress used_addr,
  176. IOAddress requested,
  177. uint8_t expected_pd_len) {
  178. boost::scoped_ptr<AllocEngine> engine;
  179. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  180. ASSERT_TRUE(engine);
  181. // Let's create a lease and put it in the LeaseMgr
  182. DuidPtr duid2 = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xff)));
  183. time_t now = time(NULL);
  184. Lease6Ptr used(new Lease6(type, used_addr,
  185. duid2, 1, 2, 3, 4, now, subnet_->getID()));
  186. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
  187. // Another client comes in and request an address that is in pool, but
  188. // unfortunately it is used already. The same address must not be allocated
  189. // twice.
  190. Lease6Ptr lease;
  191. AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, requested, type,
  192. false, false, "", false);
  193. EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
  194. // Check that we got a lease
  195. ASSERT_TRUE(lease);
  196. // Allocated address must be different
  197. EXPECT_NE(used_addr, lease->addr_);
  198. // We should NOT get what we asked for, because it is used already
  199. EXPECT_NE(requested, lease->addr_);
  200. // Do all checks on the lease
  201. checkLease6(lease, type, expected_pd_len);
  202. // Check that the lease is indeed in LeaseMgr
  203. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
  204. lease->addr_);
  205. ASSERT_TRUE(from_mgr);
  206. // Now check that the lease in LeaseMgr has the same parameters
  207. detailCompareLease(lease, from_mgr);
  208. }
  209. void
  210. AllocEngine6Test::allocBogusHint6(Lease::Type type, asiolink::IOAddress hint,
  211. uint8_t expected_pd_len) {
  212. boost::scoped_ptr<AllocEngine> engine;
  213. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  214. ASSERT_TRUE(engine);
  215. // Client would like to get a 3000::abc lease, which does not belong to any
  216. // supported lease. Allocation engine should ignore it and carry on
  217. // with the normal allocation
  218. Lease6Ptr lease;
  219. AllocEngine::ClientContext6 ctx(subnet_, duid_, iaid_, hint, type, false,
  220. false, "", false);
  221. EXPECT_NO_THROW(lease = expectOneLease(engine->allocateLeases6(ctx)));
  222. // Check that we got a lease
  223. ASSERT_TRUE(lease);
  224. // We should NOT get what we asked for, because it is used already
  225. EXPECT_NE(hint, lease->addr_);
  226. // Do all checks on the lease
  227. checkLease6(lease, type, expected_pd_len);
  228. // Check that the lease is indeed in LeaseMgr
  229. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->type_,
  230. lease->addr_);
  231. ASSERT_TRUE(from_mgr);
  232. // Now check that the lease in LeaseMgr has the same parameters
  233. detailCompareLease(lease, from_mgr);
  234. }
  235. void
  236. AllocEngine4Test::initSubnet(const asiolink::IOAddress& pool_start,
  237. const asiolink::IOAddress& pool_end) {
  238. CfgMgr& cfg_mgr = CfgMgr::instance();
  239. subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
  240. pool_ = Pool4Ptr(new Pool4(pool_start, pool_end));
  241. subnet_->addPool(pool_);
  242. cfg_mgr.getStagingCfg()->getCfgSubnets4()->add(subnet_);
  243. }
  244. AllocEngine4Test::AllocEngine4Test() {
  245. // Create fresh instance of the HostMgr, and drop any previous HostMgr state.
  246. HostMgr::instance().create();
  247. clientid_ = ClientIdPtr(new ClientId(vector<uint8_t>(8, 0x44)));
  248. uint8_t mac[] = { 0, 1, 22, 33, 44, 55};
  249. // Let's use odd hardware type to check if there is no Ethernet
  250. // hardcoded anywhere.
  251. hwaddr_ = HWAddrPtr(new HWAddr(mac, sizeof(mac), HTYPE_FDDI));
  252. // Allocate different MAC address for the tests that require two
  253. // different MAC addresses.
  254. ++mac[sizeof(mac) - 1];
  255. hwaddr2_ = HWAddrPtr(new HWAddr(mac, sizeof (mac), HTYPE_FDDI));
  256. // instantiate cfg_mgr
  257. CfgMgr& cfg_mgr = CfgMgr::instance();
  258. initSubnet(IOAddress("192.0.2.100"), IOAddress("192.0.2.109"));
  259. cfg_mgr.commit();
  260. factory_.create("type=memfile universe=4 persist=false");
  261. // Create a default context. Note that remaining parameters must be
  262. // assigned when needed.
  263. ctx_.subnet_ = subnet_;
  264. ctx_.clientid_ = clientid_;
  265. ctx_.hwaddr_ = hwaddr_;
  266. ctx_.callout_handle_ = HooksManager::createCalloutHandle();
  267. }
  268. }; // namespace test
  269. }; // namespace dhcp
  270. }; // namespace isc