alloc_engine_unittest.cc 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488
  1. // Copyright (C) 2012-2013 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 <asiolink/io_address.h>
  16. #include <dhcp/duid.h>
  17. #include <dhcp/dhcp4.h>
  18. #include <dhcpsrv/alloc_engine.h>
  19. #include <dhcpsrv/cfgmgr.h>
  20. #include <dhcpsrv/lease_mgr.h>
  21. #include <dhcpsrv/lease_mgr_factory.h>
  22. #include <dhcpsrv/memfile_lease_mgr.h>
  23. #include <dhcpsrv/tests/test_utils.h>
  24. #include <hooks/server_hooks.h>
  25. #include <hooks/callout_manager.h>
  26. #include <hooks/hooks_manager.h>
  27. #include <boost/shared_ptr.hpp>
  28. #include <boost/scoped_ptr.hpp>
  29. #include <gtest/gtest.h>
  30. #include <iostream>
  31. #include <sstream>
  32. #include <algorithm>
  33. #include <set>
  34. #include <time.h>
  35. using namespace std;
  36. using namespace isc;
  37. using namespace isc::asiolink;
  38. using namespace isc::hooks;
  39. using namespace isc::dhcp;
  40. using namespace isc::dhcp::test;
  41. namespace {
  42. /// @brief Allocation engine with some internal methods exposed
  43. class NakedAllocEngine : public AllocEngine {
  44. public:
  45. /// @brief the sole constructor
  46. /// @param engine_type specifies engine type (e.g. iterative)
  47. /// @param attempts number of lease selection attempts before giving up
  48. NakedAllocEngine(AllocEngine::AllocType engine_type, unsigned int attempts)
  49. :AllocEngine(engine_type, attempts) {
  50. }
  51. // Expose internal classes for testing purposes
  52. using AllocEngine::Allocator;
  53. using AllocEngine::IterativeAllocator;
  54. };
  55. /// @brief Used in Allocation Engine tests for IPv6
  56. class AllocEngine6Test : public ::testing::Test {
  57. public:
  58. /// @brief Default constructor
  59. ///
  60. /// Sets duid_, iaid_, subnet_, pool_ fields to example values used
  61. /// in many tests, initializes cfg_mgr configuration and creates
  62. /// lease database.
  63. AllocEngine6Test() {
  64. duid_ = DuidPtr(new DUID(vector<uint8_t>(8, 0x42)));
  65. iaid_ = 42;
  66. // instantiate cfg_mgr
  67. CfgMgr& cfg_mgr = CfgMgr::instance();
  68. subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  69. pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1::10"),
  70. IOAddress("2001:db8:1::20")));
  71. subnet_->addPool(pool_);
  72. cfg_mgr.addSubnet6(subnet_);
  73. factory_.create("type=memfile");
  74. }
  75. /// @brief checks if Lease6 matches expected configuration
  76. ///
  77. /// @param lease lease to be checked
  78. void checkLease6(const Lease6Ptr& lease) {
  79. // that is belongs to the right subnet
  80. EXPECT_EQ(lease->subnet_id_, subnet_->getID());
  81. EXPECT_TRUE(subnet_->inRange(lease->addr_));
  82. EXPECT_TRUE(subnet_->inPool(lease->addr_));
  83. // that it have proper parameters
  84. EXPECT_EQ(iaid_, lease->iaid_);
  85. EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
  86. EXPECT_EQ(subnet_->getPreferred(), lease->preferred_lft_);
  87. EXPECT_EQ(subnet_->getT1(), lease->t1_);
  88. EXPECT_EQ(subnet_->getT2(), lease->t2_);
  89. EXPECT_EQ(0, lease->prefixlen_); // this is IA_NA, not IA_PD
  90. EXPECT_TRUE(false == lease->fqdn_fwd_);
  91. EXPECT_TRUE(false == lease->fqdn_rev_);
  92. EXPECT_TRUE(*lease->duid_ == *duid_);
  93. // @todo: check cltt
  94. }
  95. virtual ~AllocEngine6Test() {
  96. factory_.destroy();
  97. }
  98. DuidPtr duid_; ///< client-identifier (value used in tests)
  99. uint32_t iaid_; ///< IA identifier (value used in tests)
  100. Subnet6Ptr subnet_; ///< subnet6 (used in tests)
  101. Pool6Ptr pool_; ///< pool belonging to subnet_
  102. LeaseMgrFactory factory_; ///< pointer to LeaseMgr factory
  103. };
  104. /// @brief Used in Allocation Engine tests for IPv4
  105. class AllocEngine4Test : public ::testing::Test {
  106. public:
  107. /// @brief Default constructor
  108. ///
  109. /// Sets clientid_, hwaddr_, subnet_, pool_ fields to example values
  110. /// used in many tests, initializes cfg_mgr configuration and creates
  111. /// lease database.
  112. AllocEngine4Test() {
  113. clientid_ = ClientIdPtr(new ClientId(vector<uint8_t>(8, 0x44)));
  114. static uint8_t mac[] = { 0, 1, 22, 33, 44, 55};
  115. // Let's use odd hardware type to check if there is no Ethernet
  116. // hardcoded anywhere.
  117. hwaddr_ = HWAddrPtr(new HWAddr(mac, sizeof(mac), HTYPE_FDDI));
  118. // instantiate cfg_mgr
  119. CfgMgr& cfg_mgr = CfgMgr::instance();
  120. subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
  121. pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"),
  122. IOAddress("192.0.2.109")));
  123. subnet_->addPool(pool_);
  124. cfg_mgr.addSubnet4(subnet_);
  125. factory_.create("type=memfile");
  126. }
  127. /// @brief checks if Lease4 matches expected configuration
  128. ///
  129. /// @param lease lease to be checked
  130. void checkLease4(const Lease4Ptr& lease) {
  131. // Check that is belongs to the right subnet
  132. EXPECT_EQ(lease->subnet_id_, subnet_->getID());
  133. EXPECT_TRUE(subnet_->inRange(lease->addr_));
  134. EXPECT_TRUE(subnet_->inPool(lease->addr_));
  135. // Check that it has proper parameters
  136. EXPECT_EQ(subnet_->getValid(), lease->valid_lft_);
  137. EXPECT_EQ(subnet_->getT1(), lease->t1_);
  138. EXPECT_EQ(subnet_->getT2(), lease->t2_);
  139. EXPECT_TRUE(false == lease->fqdn_fwd_);
  140. EXPECT_TRUE(false == lease->fqdn_rev_);
  141. if (lease->client_id_ && !clientid_) {
  142. ADD_FAILURE() << "Lease4 has a client-id, while it should have none.";
  143. } else
  144. if (!lease->client_id_ && clientid_) {
  145. ADD_FAILURE() << "Lease4 has no client-id, but it was expected to have one.";
  146. } else
  147. if (lease->client_id_ && clientid_) {
  148. EXPECT_TRUE(*lease->client_id_ == *clientid_);
  149. }
  150. EXPECT_TRUE(lease->hwaddr_ == hwaddr_->hwaddr_);
  151. // @todo: check cltt
  152. }
  153. virtual ~AllocEngine4Test() {
  154. factory_.destroy();
  155. }
  156. ClientIdPtr clientid_; ///< Client-identifier (value used in tests)
  157. HWAddrPtr hwaddr_; ///< Hardware address (value used in tests)
  158. Subnet4Ptr subnet_; ///< Subnet4 (used in tests)
  159. Pool4Ptr pool_; ///< Pool belonging to subnet_
  160. LeaseMgrFactory factory_; ///< Pointer to LeaseMgr factory
  161. };
  162. // This test checks if the Allocation Engine can be instantiated and that it
  163. // parses parameters string properly.
  164. TEST_F(AllocEngine6Test, constructor) {
  165. boost::scoped_ptr<AllocEngine> x;
  166. // Hashed and random allocators are not supported yet
  167. ASSERT_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_HASHED, 5)), NotImplemented);
  168. ASSERT_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_RANDOM, 5)), NotImplemented);
  169. ASSERT_NO_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  170. }
  171. // This test checks if the simple allocation can succeed
  172. TEST_F(AllocEngine6Test, simpleAlloc6) {
  173. boost::scoped_ptr<AllocEngine> engine;
  174. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  175. ASSERT_TRUE(engine);
  176. Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
  177. IOAddress("::"), false,
  178. false, "",
  179. false, CalloutHandlePtr());
  180. // Check that we got a lease
  181. ASSERT_TRUE(lease);
  182. // Do all checks on the lease
  183. checkLease6(lease);
  184. // Check that the lease is indeed in LeaseMgr
  185. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
  186. ASSERT_TRUE(from_mgr);
  187. // Now check that the lease in LeaseMgr has the same parameters
  188. detailCompareLease(lease, from_mgr);
  189. }
  190. // This test checks if the fake allocation (for SOLICIT) can succeed
  191. TEST_F(AllocEngine6Test, fakeAlloc6) {
  192. boost::scoped_ptr<AllocEngine> engine;
  193. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  194. ASSERT_TRUE(engine);
  195. Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
  196. IOAddress("::"), false,
  197. false, "", true,
  198. CalloutHandlePtr());
  199. // Check that we got a lease
  200. ASSERT_TRUE(lease);
  201. // Do all checks on the lease
  202. checkLease6(lease);
  203. // Check that the lease is NOT in LeaseMgr
  204. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
  205. ASSERT_FALSE(from_mgr);
  206. }
  207. // This test checks if the allocation with a hint that is valid (in range,
  208. // in pool and free) can succeed
  209. TEST_F(AllocEngine6Test, allocWithValidHint6) {
  210. boost::scoped_ptr<AllocEngine> engine;
  211. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  212. ASSERT_TRUE(engine);
  213. Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
  214. IOAddress("2001:db8:1::15"),
  215. false, false, "",
  216. false, CalloutHandlePtr());
  217. // Check that we got a lease
  218. ASSERT_TRUE(lease);
  219. // We should get what we asked for
  220. EXPECT_EQ(lease->addr_.toText(), "2001:db8:1::15");
  221. // Do all checks on the lease
  222. checkLease6(lease);
  223. // Check that the lease is indeed in LeaseMgr
  224. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
  225. ASSERT_TRUE(from_mgr);
  226. // Now check that the lease in LeaseMgr has the same parameters
  227. detailCompareLease(lease, from_mgr);
  228. }
  229. // This test checks if the allocation with a hint that is in range,
  230. // in pool, but is currently used) can succeed
  231. TEST_F(AllocEngine6Test, allocWithUsedHint6) {
  232. boost::scoped_ptr<AllocEngine> engine;
  233. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  234. ASSERT_TRUE(engine);
  235. // Let's create a lease and put it in the LeaseMgr
  236. DuidPtr duid2 = boost::shared_ptr<DUID>(new DUID(vector<uint8_t>(8, 0xff)));
  237. time_t now = time(NULL);
  238. Lease6Ptr used(new Lease6(Lease6::LEASE_IA_NA, IOAddress("2001:db8:1::1f"),
  239. duid2, 1, 2, 3, 4, now, subnet_->getID()));
  240. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
  241. // Another client comes in and request an address that is in pool, but
  242. // unfortunately it is used already. The same address must not be allocated
  243. // twice.
  244. Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
  245. IOAddress("2001:db8:1::1f"),
  246. false, false, "",
  247. false, CalloutHandlePtr());
  248. // Check that we got a lease
  249. ASSERT_TRUE(lease);
  250. // Allocated address must be different
  251. EXPECT_TRUE(used->addr_.toText() != lease->addr_.toText());
  252. // We should NOT get what we asked for, because it is used already
  253. EXPECT_TRUE(lease->addr_.toText() != "2001:db8:1::1f");
  254. // Do all checks on the lease
  255. checkLease6(lease);
  256. // Check that the lease is indeed in LeaseMgr
  257. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
  258. ASSERT_TRUE(from_mgr);
  259. // Now check that the lease in LeaseMgr has the same parameters
  260. detailCompareLease(lease, from_mgr);
  261. }
  262. // This test checks if the allocation with a hint that is out the blue
  263. // can succeed. The invalid hint should be ignored completely.
  264. TEST_F(AllocEngine6Test, allocBogusHint6) {
  265. boost::scoped_ptr<AllocEngine> engine;
  266. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  267. ASSERT_TRUE(engine);
  268. // Client would like to get a 3000::abc lease, which does not belong to any
  269. // supported lease. Allocation engine should ignore it and carry on
  270. // with the normal allocation
  271. Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
  272. IOAddress("3000::abc"),
  273. false, false, "",
  274. false, CalloutHandlePtr());
  275. // Check that we got a lease
  276. ASSERT_TRUE(lease);
  277. // We should NOT get what we asked for, because it is used already
  278. EXPECT_TRUE(lease->addr_.toText() != "3000::abc");
  279. // Do all checks on the lease
  280. checkLease6(lease);
  281. // Check that the lease is indeed in LeaseMgr
  282. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
  283. ASSERT_TRUE(from_mgr);
  284. // Now check that the lease in LeaseMgr has the same parameters
  285. detailCompareLease(lease, from_mgr);
  286. }
  287. // This test checks that NULL values are handled properly
  288. TEST_F(AllocEngine6Test, allocateAddress6Nulls) {
  289. boost::scoped_ptr<AllocEngine> engine;
  290. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  291. ASSERT_TRUE(engine);
  292. // Allocations without subnet are not allowed
  293. Lease6Ptr lease = engine->allocateAddress6(Subnet6Ptr(), duid_, iaid_,
  294. IOAddress("::"),
  295. false, false, "", false,
  296. CalloutHandlePtr());
  297. ASSERT_FALSE(lease);
  298. // Allocations without DUID are not allowed either
  299. lease = engine->allocateAddress6(subnet_, DuidPtr(), iaid_,
  300. IOAddress("::"),
  301. false, false, "", false,
  302. CalloutHandlePtr());
  303. ASSERT_FALSE(lease);
  304. }
  305. // This test verifies that the allocator picks addresses that belong to the
  306. // pool
  307. TEST_F(AllocEngine6Test, IterativeAllocator) {
  308. boost::scoped_ptr<NakedAllocEngine::Allocator>
  309. alloc(new NakedAllocEngine::IterativeAllocator());
  310. for (int i = 0; i < 1000; ++i) {
  311. IOAddress candidate = alloc->pickAddress(subnet_, duid_, IOAddress("::"));
  312. EXPECT_TRUE(subnet_->inPool(candidate));
  313. }
  314. }
  315. // This test verifies that the iterative allocator really walks over all addresses
  316. // in all pools in specified subnet. It also must not pick the same address twice
  317. // unless it runs out of pool space and must start over.
  318. TEST_F(AllocEngine6Test, IterativeAllocator_manyPools6) {
  319. NakedAllocEngine::IterativeAllocator alloc;
  320. // let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
  321. for (int i = 2; i < 10; ++i) {
  322. stringstream min, max;
  323. min << "2001:db8:1::" << hex << i*16 + 1;
  324. max << "2001:db8:1::" << hex << i*16 + 9;
  325. Pool6Ptr pool(new Pool6(Pool6::TYPE_IA, IOAddress(min.str()),
  326. IOAddress(max.str())));
  327. subnet_->addPool(pool);
  328. }
  329. int total = 17 + 8 * 9; // First pool (::10 - ::20) has 17 addresses in it,
  330. // there are 8 extra pools with 9 addresses in each.
  331. // Let's keep picked addresses here and check their uniqueness.
  332. std::set<IOAddress> generated_addrs;
  333. int cnt = 0;
  334. while (++cnt) {
  335. IOAddress candidate = alloc.pickAddress(subnet_, duid_, IOAddress("::"));
  336. EXPECT_TRUE(subnet_->inPool(candidate));
  337. // One way to easily verify that the iterative allocator really works is
  338. // to uncomment the following line and observe its output that it
  339. // covers all defined subnets.
  340. // cout << candidate.toText() << endl;
  341. if (generated_addrs.find(candidate) == generated_addrs.end()) {
  342. // We haven't had this.
  343. generated_addrs.insert(candidate);
  344. } else {
  345. // We have seen this address before. That should mean that we
  346. // iterated over all addresses.
  347. if (generated_addrs.size() == total) {
  348. // We have exactly the number of address in all pools.
  349. break;
  350. }
  351. ADD_FAILURE() << "Too many or not enough unique addresses generated.";
  352. break;
  353. }
  354. if ( cnt>total ) {
  355. ADD_FAILURE() << "Too many unique addresses generated.";
  356. break;
  357. }
  358. }
  359. }
  360. // This test checks if really small pools are working
  361. TEST_F(AllocEngine6Test, smallPool6) {
  362. boost::scoped_ptr<AllocEngine> engine;
  363. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  364. ASSERT_TRUE(engine);
  365. IOAddress addr("2001:db8:1::ad");
  366. CfgMgr& cfg_mgr = CfgMgr::instance();
  367. cfg_mgr.deleteSubnets6(); // Get rid of the default test configuration
  368. // Create configuration similar to other tests, but with a single address pool
  369. subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  370. pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, addr, addr)); // just a single address
  371. subnet_->addPool(pool_);
  372. cfg_mgr.addSubnet6(subnet_);
  373. Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_,
  374. IOAddress("::"),
  375. false, false, "",
  376. false, CalloutHandlePtr());
  377. // Check that we got that single lease
  378. ASSERT_TRUE(lease);
  379. EXPECT_EQ("2001:db8:1::ad", lease->addr_.toText());
  380. // Do all checks on the lease
  381. checkLease6(lease);
  382. // Check that the lease is indeed in LeaseMgr
  383. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
  384. ASSERT_TRUE(from_mgr);
  385. // Now check that the lease in LeaseMgr has the same parameters
  386. detailCompareLease(lease, from_mgr);
  387. }
  388. // This test checks if all addresses in a pool are currently used, the attempt
  389. // to find out a new lease fails.
  390. TEST_F(AllocEngine6Test, outOfAddresses6) {
  391. boost::scoped_ptr<AllocEngine> engine;
  392. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  393. ASSERT_TRUE(engine);
  394. IOAddress addr("2001:db8:1::ad");
  395. CfgMgr& cfg_mgr = CfgMgr::instance();
  396. cfg_mgr.deleteSubnets6(); // Get rid of the default test configuration
  397. // Create configuration similar to other tests, but with a single address pool
  398. subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  399. pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, addr, addr)); // just a single address
  400. subnet_->addPool(pool_);
  401. cfg_mgr.addSubnet6(subnet_);
  402. // Just a different duid
  403. DuidPtr other_duid = DuidPtr(new DUID(vector<uint8_t>(12, 0xff)));
  404. const uint32_t other_iaid = 3568;
  405. Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, other_duid, other_iaid,
  406. 501, 502, 503, 504, subnet_->getID(), 0));
  407. lease->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
  408. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  409. // There is just a single address in the pool and allocated it to someone
  410. // else, so the allocation should fail
  411. Lease6Ptr lease2 = engine->allocateAddress6(subnet_, duid_, iaid_,
  412. IOAddress("::"),
  413. false, false, "", false,
  414. CalloutHandlePtr());
  415. EXPECT_FALSE(lease2);
  416. }
  417. // This test checks if an expired lease can be reused in SOLICIT (fake allocation)
  418. TEST_F(AllocEngine6Test, solicitReuseExpiredLease6) {
  419. boost::scoped_ptr<AllocEngine> engine;
  420. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  421. ASSERT_TRUE(engine);
  422. IOAddress addr("2001:db8:1::ad");
  423. CfgMgr& cfg_mgr = CfgMgr::instance();
  424. cfg_mgr.deleteSubnets6(); // Get rid of the default test configuration
  425. // Create configuration similar to other tests, but with a single address pool
  426. subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  427. pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, addr, addr)); // just a single address
  428. subnet_->addPool(pool_);
  429. cfg_mgr.addSubnet6(subnet_);
  430. // Just a different duid
  431. DuidPtr other_duid = DuidPtr(new DUID(vector<uint8_t>(12, 0xff)));
  432. const uint32_t other_iaid = 3568;
  433. Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, other_duid, other_iaid,
  434. 501, 502, 503, 504, subnet_->getID(), 0));
  435. lease->cltt_ = time(NULL) - 500; // Allocated 500 seconds ago
  436. lease->valid_lft_ = 495; // Lease was valid for 495 seconds
  437. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  438. // Make sure that we really created expired lease
  439. ASSERT_TRUE(lease->expired());
  440. // CASE 1: Asking for any address
  441. lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
  442. false, false, "",
  443. true, CalloutHandlePtr());
  444. // Check that we got that single lease
  445. ASSERT_TRUE(lease);
  446. EXPECT_EQ(addr.toText(), lease->addr_.toText());
  447. // Do all checks on the lease (if subnet-id, preferred/valid times are ok etc.)
  448. checkLease6(lease);
  449. // CASE 2: Asking specifically for this address
  450. lease = engine->allocateAddress6(subnet_, duid_, iaid_,
  451. IOAddress(addr.toText()),
  452. false, false, "",
  453. true, CalloutHandlePtr());
  454. // Check that we got that single lease
  455. ASSERT_TRUE(lease);
  456. EXPECT_EQ(addr.toText(), lease->addr_.toText());
  457. }
  458. // This test checks if an expired lease can be reused in REQUEST (actual allocation)
  459. TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
  460. boost::scoped_ptr<AllocEngine> engine;
  461. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  462. ASSERT_TRUE(engine);
  463. IOAddress addr("2001:db8:1::ad");
  464. CfgMgr& cfg_mgr = CfgMgr::instance();
  465. cfg_mgr.deleteSubnets6(); // Get rid of the default test configuration
  466. // Create configuration similar to other tests, but with a single address pool
  467. subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
  468. pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, addr, addr)); // just a single address
  469. subnet_->addPool(pool_);
  470. cfg_mgr.addSubnet6(subnet_);
  471. // Let's create an expired lease
  472. DuidPtr other_duid = DuidPtr(new DUID(vector<uint8_t>(12, 0xff)));
  473. const uint32_t other_iaid = 3568;
  474. const SubnetID other_subnetid = 999;
  475. Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, other_duid, other_iaid,
  476. 501, 502, 503, 504, other_subnetid, 0));
  477. lease->cltt_ = time(NULL) - 500; // Allocated 500 seconds ago
  478. lease->valid_lft_ = 495; // Lease was valid for 495 seconds
  479. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  480. // A client comes along, asking specifically for this address
  481. lease = engine->allocateAddress6(subnet_, duid_, iaid_,
  482. IOAddress(addr.toText()),
  483. false, false, "", false,
  484. CalloutHandlePtr());
  485. // Check that he got that single lease
  486. ASSERT_TRUE(lease);
  487. EXPECT_EQ(addr.toText(), lease->addr_.toText());
  488. // Check that the lease is indeed updated in LeaseMgr
  489. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(addr);
  490. ASSERT_TRUE(from_mgr);
  491. // Now check that the lease in LeaseMgr has the same parameters
  492. detailCompareLease(lease, from_mgr);
  493. }
  494. // --- IPv4 ---
  495. // This test checks if the simple IPv4 allocation can succeed
  496. TEST_F(AllocEngine4Test, simpleAlloc4) {
  497. boost::scoped_ptr<AllocEngine> engine;
  498. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  499. ASSERT_TRUE(engine);
  500. Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
  501. IOAddress("0.0.0.0"), false,
  502. CalloutHandlePtr());
  503. // Check that we got a lease
  504. ASSERT_TRUE(lease);
  505. // Do all checks on the lease
  506. checkLease4(lease);
  507. // Check that the lease is indeed in LeaseMgr
  508. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
  509. ASSERT_TRUE(from_mgr);
  510. // Now check that the lease in LeaseMgr has the same parameters
  511. detailCompareLease(lease, from_mgr);
  512. }
  513. // This test checks if the fake allocation (for DISCOVER) can succeed
  514. TEST_F(AllocEngine4Test, fakeAlloc4) {
  515. boost::scoped_ptr<AllocEngine> engine;
  516. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  517. ASSERT_TRUE(engine);
  518. Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
  519. IOAddress("0.0.0.0"), true,
  520. CalloutHandlePtr());
  521. // Check that we got a lease
  522. ASSERT_TRUE(lease);
  523. // Do all checks on the lease
  524. checkLease4(lease);
  525. // Check that the lease is NOT in LeaseMgr
  526. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
  527. ASSERT_FALSE(from_mgr);
  528. }
  529. // This test checks if the allocation with a hint that is valid (in range,
  530. // in pool and free) can succeed
  531. TEST_F(AllocEngine4Test, allocWithValidHint4) {
  532. boost::scoped_ptr<AllocEngine> engine;
  533. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  534. ASSERT_TRUE(engine);
  535. Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
  536. IOAddress("192.0.2.105"),
  537. false, CalloutHandlePtr());
  538. // Check that we got a lease
  539. ASSERT_TRUE(lease);
  540. // We should get what we asked for
  541. EXPECT_EQ(lease->addr_.toText(), "192.0.2.105");
  542. // Do all checks on the lease
  543. checkLease4(lease);
  544. // Check that the lease is indeed in LeaseMgr
  545. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
  546. ASSERT_TRUE(from_mgr);
  547. // Now check that the lease in LeaseMgr has the same parameters
  548. detailCompareLease(lease, from_mgr);
  549. }
  550. // This test checks if the allocation with a hint that is in range,
  551. // in pool, but is currently used) can succeed
  552. TEST_F(AllocEngine4Test, allocWithUsedHint4) {
  553. boost::scoped_ptr<AllocEngine> engine;
  554. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  555. ASSERT_TRUE(engine);
  556. // Let's create a lease and put it in the LeaseMgr
  557. uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
  558. uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
  559. time_t now = time(NULL);
  560. Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2, sizeof(hwaddr2),
  561. clientid2, sizeof(clientid2), 1, 2, 3, now, subnet_->getID()));
  562. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
  563. // Another client comes in and request an address that is in pool, but
  564. // unfortunately it is used already. The same address must not be allocated
  565. // twice.
  566. Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
  567. IOAddress("192.0.2.106"),
  568. false, CalloutHandlePtr());
  569. // Check that we got a lease
  570. ASSERT_TRUE(lease);
  571. // Allocated address must be different
  572. EXPECT_TRUE(used->addr_.toText() != lease->addr_.toText());
  573. // We should NOT get what we asked for, because it is used already
  574. EXPECT_TRUE(lease->addr_.toText() != "192.0.2.106");
  575. // Do all checks on the lease
  576. checkLease4(lease);
  577. // Check that the lease is indeed in LeaseMgr
  578. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
  579. ASSERT_TRUE(from_mgr);
  580. // Now check that the lease in LeaseMgr has the same parameters
  581. detailCompareLease(lease, from_mgr);
  582. }
  583. // This test checks if the allocation with a hint that is out the blue
  584. // can succeed. The invalid hint should be ignored completely.
  585. TEST_F(AllocEngine4Test, allocBogusHint4) {
  586. boost::scoped_ptr<AllocEngine> engine;
  587. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  588. ASSERT_TRUE(engine);
  589. // Client would like to get a 3000::abc lease, which does not belong to any
  590. // supported lease. Allocation engine should ignore it and carry on
  591. // with the normal allocation
  592. Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
  593. IOAddress("10.1.1.1"),
  594. false, CalloutHandlePtr());
  595. // Check that we got a lease
  596. ASSERT_TRUE(lease);
  597. // We should NOT get what we asked for, because it is used already
  598. EXPECT_TRUE(lease->addr_.toText() != "10.1.1.1");
  599. // Do all checks on the lease
  600. checkLease4(lease);
  601. // Check that the lease is indeed in LeaseMgr
  602. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
  603. ASSERT_TRUE(from_mgr);
  604. // Now check that the lease in LeaseMgr has the same parameters
  605. detailCompareLease(lease, from_mgr);
  606. }
  607. // This test checks that NULL values are handled properly
  608. TEST_F(AllocEngine4Test, allocateAddress4Nulls) {
  609. boost::scoped_ptr<AllocEngine> engine;
  610. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  611. ASSERT_TRUE(engine);
  612. // Allocations without subnet are not allowed
  613. Lease4Ptr lease = engine->allocateAddress4(SubnetPtr(), clientid_, hwaddr_,
  614. IOAddress("0.0.0.0"), false,
  615. CalloutHandlePtr());
  616. EXPECT_FALSE(lease);
  617. // Allocations without HW address are not allowed
  618. lease = engine->allocateAddress4(subnet_, clientid_, HWAddrPtr(),
  619. IOAddress("0.0.0.0"), false, CalloutHandlePtr());
  620. EXPECT_FALSE(lease);
  621. // Allocations without client-id are allowed
  622. clientid_ = ClientIdPtr();
  623. lease = engine->allocateAddress4(subnet_, ClientIdPtr(), hwaddr_,
  624. IOAddress("0.0.0.0"), false, CalloutHandlePtr());
  625. // Check that we got a lease
  626. ASSERT_TRUE(lease);
  627. // Do all checks on the lease
  628. checkLease4(lease);
  629. // Check that the lease is indeed in LeaseMgr
  630. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
  631. ASSERT_TRUE(from_mgr);
  632. // Now check that the lease in LeaseMgr has the same parameters
  633. detailCompareLease(lease, from_mgr);
  634. }
  635. // This test verifies that the allocator picks addresses that belong to the
  636. // pool
  637. TEST_F(AllocEngine4Test, IterativeAllocator) {
  638. boost::scoped_ptr<NakedAllocEngine::Allocator>
  639. alloc(new NakedAllocEngine::IterativeAllocator());
  640. for (int i = 0; i < 1000; ++i) {
  641. IOAddress candidate = alloc->pickAddress(subnet_, clientid_,
  642. IOAddress("0.0.0.0"));
  643. EXPECT_TRUE(subnet_->inPool(candidate));
  644. }
  645. }
  646. // This test verifies that the iterative allocator really walks over all addresses
  647. // in all pools in specified subnet. It also must not pick the same address twice
  648. // unless it runs out of pool space and must start over.
  649. TEST_F(AllocEngine4Test, IterativeAllocator_manyPools4) {
  650. NakedAllocEngine::IterativeAllocator alloc;
  651. // Let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
  652. for (int i = 2; i < 10; ++i) {
  653. stringstream min, max;
  654. min << "192.0.2." << i * 10 + 1;
  655. max << "192.0.2." << i * 10 + 9;
  656. Pool4Ptr pool(new Pool4(IOAddress(min.str()),
  657. IOAddress(max.str())));
  658. // cout << "Adding pool: " << min.str() << "-" << max.str() << endl;
  659. subnet_->addPool(pool);
  660. }
  661. int total = 10 + 8 * 9; // first pool (.100 - .109) has 10 addresses in it,
  662. // there are 8 extra pools with 9 addresses in each.
  663. // Let's keep picked addresses here and check their uniqueness.
  664. std::set<IOAddress> generated_addrs;
  665. int cnt = 0;
  666. while (++cnt) {
  667. IOAddress candidate = alloc.pickAddress(subnet_, clientid_, IOAddress("0.0.0.0"));
  668. EXPECT_TRUE(subnet_->inPool(candidate));
  669. // One way to easily verify that the iterative allocator really works is
  670. // to uncomment the following line and observe its output that it
  671. // covers all defined subnets.
  672. // cout << candidate.toText() << endl;
  673. if (generated_addrs.find(candidate) == generated_addrs.end()) {
  674. // We haven't had this
  675. generated_addrs.insert(candidate);
  676. } else {
  677. // We have seen this address before. That should mean that we
  678. // iterated over all addresses.
  679. if (generated_addrs.size() == total) {
  680. // We have exactly the number of address in all pools
  681. break;
  682. }
  683. ADD_FAILURE() << "Too many or not enough unique addresses generated.";
  684. break;
  685. }
  686. if ( cnt>total ) {
  687. ADD_FAILURE() << "Too many unique addresses generated.";
  688. break;
  689. }
  690. }
  691. }
  692. // This test checks if really small pools are working
  693. TEST_F(AllocEngine4Test, smallPool4) {
  694. boost::scoped_ptr<AllocEngine> engine;
  695. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  696. ASSERT_TRUE(engine);
  697. IOAddress addr("192.0.2.17");
  698. CfgMgr& cfg_mgr = CfgMgr::instance();
  699. cfg_mgr.deleteSubnets4(); // Get rid of the default test configuration
  700. // Create configuration similar to other tests, but with a single address pool
  701. subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
  702. pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
  703. subnet_->addPool(pool_);
  704. cfg_mgr.addSubnet4(subnet_);
  705. Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
  706. false, CalloutHandlePtr());
  707. // Check that we got that single lease
  708. ASSERT_TRUE(lease);
  709. EXPECT_EQ("192.0.2.17", lease->addr_.toText());
  710. // Do all checks on the lease
  711. checkLease4(lease);
  712. // Check that the lease is indeed in LeaseMgr
  713. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
  714. ASSERT_TRUE(from_mgr);
  715. // Now check that the lease in LeaseMgr has the same parameters
  716. detailCompareLease(lease, from_mgr);
  717. }
  718. // This test checks if all addresses in a pool are currently used, the attempt
  719. // to find out a new lease fails.
  720. TEST_F(AllocEngine4Test, outOfAddresses4) {
  721. boost::scoped_ptr<AllocEngine> engine;
  722. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  723. ASSERT_TRUE(engine);
  724. IOAddress addr("192.0.2.17");
  725. CfgMgr& cfg_mgr = CfgMgr::instance();
  726. cfg_mgr.deleteSubnets4(); // Get rid of the default test configuration
  727. // Create configuration similar to other tests, but with a single address pool
  728. subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
  729. pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
  730. subnet_->addPool(pool_);
  731. cfg_mgr.addSubnet4(subnet_);
  732. // Just a different hw/client-id for the second client
  733. uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
  734. uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
  735. time_t now = time(NULL);
  736. Lease4Ptr lease(new Lease4(addr, hwaddr2, sizeof(hwaddr2), clientid2, sizeof(clientid2),
  737. 501, 502, 503, now, subnet_->getID()));
  738. lease->cltt_ = time(NULL) - 10; // Allocated 10 seconds ago
  739. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  740. // There is just a single address in the pool and allocated it to someone
  741. // else, so the allocation should fail
  742. Lease4Ptr lease2 = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
  743. IOAddress("0.0.0.0"), false,
  744. CalloutHandlePtr());
  745. EXPECT_FALSE(lease2);
  746. }
  747. // This test checks if an expired lease can be reused in DISCOVER (fake allocation)
  748. TEST_F(AllocEngine4Test, discoverReuseExpiredLease4) {
  749. boost::scoped_ptr<AllocEngine> engine;
  750. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  751. ASSERT_TRUE(engine);
  752. IOAddress addr("192.0.2.15");
  753. CfgMgr& cfg_mgr = CfgMgr::instance();
  754. cfg_mgr.deleteSubnets4(); // Get rid of the default test configuration
  755. // Create configuration similar to other tests, but with a single address pool
  756. subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1, 2, 3));
  757. pool_ = Pool4Ptr(new Pool4(addr, addr)); // just a single address
  758. subnet_->addPool(pool_);
  759. cfg_mgr.addSubnet4(subnet_);
  760. // Just a different hw/client-id for the second client
  761. uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
  762. uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
  763. time_t now = time(NULL) - 500; // Allocated 500 seconds ago
  764. Lease4Ptr lease(new Lease4(addr, clientid2, sizeof(clientid2), hwaddr2, sizeof(hwaddr2),
  765. 495, 100, 200, now, subnet_->getID()));
  766. // Lease was assigned 500 seconds ago, but its valid lifetime is 495, so it
  767. // is expired already
  768. ASSERT_TRUE(lease->expired());
  769. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  770. // CASE 1: Asking for any address
  771. lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
  772. true, CalloutHandlePtr());
  773. // Check that we got that single lease
  774. ASSERT_TRUE(lease);
  775. EXPECT_EQ(addr.toText(), lease->addr_.toText());
  776. // Do all checks on the lease (if subnet-id, preferred/valid times are ok etc.)
  777. checkLease4(lease);
  778. // CASE 2: Asking specifically for this address
  779. lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress(addr.toText()),
  780. true, CalloutHandlePtr());
  781. // Check that we got that single lease
  782. ASSERT_TRUE(lease);
  783. EXPECT_EQ(addr.toText(), lease->addr_.toText());
  784. }
  785. // This test checks if an expired lease can be reused in REQUEST (actual allocation)
  786. TEST_F(AllocEngine4Test, requestReuseExpiredLease4) {
  787. boost::scoped_ptr<AllocEngine> engine;
  788. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  789. ASSERT_TRUE(engine);
  790. IOAddress addr("192.0.2.105");
  791. // Just a different hw/client-id for the second client
  792. uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
  793. uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
  794. time_t now = time(NULL) - 500; // Allocated 500 seconds ago
  795. Lease4Ptr lease(new Lease4(addr, clientid2, sizeof(clientid2), hwaddr2, sizeof(hwaddr2),
  796. 495, 100, 200, now, subnet_->getID()));
  797. // Lease was assigned 500 seconds ago, but its valid lifetime is 495, so it
  798. // is expired already
  799. ASSERT_TRUE(lease->expired());
  800. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  801. // A client comes along, asking specifically for this address
  802. lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
  803. IOAddress(addr.toText()), false,
  804. CalloutHandlePtr());
  805. // Check that he got that single lease
  806. ASSERT_TRUE(lease);
  807. EXPECT_EQ(addr.toText(), lease->addr_.toText());
  808. // Check that the lease is indeed updated in LeaseMgr
  809. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(addr);
  810. ASSERT_TRUE(from_mgr);
  811. // Now check that the lease in LeaseMgr has the same parameters
  812. detailCompareLease(lease, from_mgr);
  813. }
  814. /// @todo write renewLease6
  815. // This test checks if a lease is really renewed when renewLease4 method is
  816. // called
  817. TEST_F(AllocEngine4Test, renewLease4) {
  818. boost::scoped_ptr<AllocEngine> engine;
  819. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  820. ASSERT_TRUE(engine);
  821. IOAddress addr("192.0.2.102");
  822. const uint32_t old_lifetime = 100;
  823. const uint32_t old_t1 = 50;
  824. const uint32_t old_t2 = 75;
  825. const time_t old_timestamp = time(NULL) - 45; // Allocated 45 seconds ago
  826. // Just a different hw/client-id for the second client
  827. const uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
  828. const uint8_t clientid2[] = { 8, 7, 6, 5, 4, 3, 2, 1 };
  829. Lease4Ptr lease(new Lease4(addr, clientid2, sizeof(clientid2), hwaddr2,
  830. sizeof(hwaddr2), old_lifetime, old_t1, old_t2,
  831. old_timestamp, subnet_->getID()));
  832. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  833. // Lease was assigned 45 seconds ago and is valid for 100 seconds. Let's
  834. // renew it.
  835. ASSERT_FALSE(lease->expired());
  836. lease = engine->renewLease4(subnet_, clientid_, hwaddr_, lease, false);
  837. // Check that he got that single lease
  838. ASSERT_TRUE(lease);
  839. EXPECT_EQ(addr.toText(), lease->addr_.toText());
  840. // Check that the lease matches subnet_, hwaddr_,clientid_ parameters
  841. checkLease4(lease);
  842. // Check that the lease is indeed updated in LeaseMgr
  843. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(addr);
  844. ASSERT_TRUE(from_mgr);
  845. // Now check that the lease in LeaseMgr has the same parameters
  846. detailCompareLease(lease, from_mgr);
  847. }
  848. /// @brief helper class used in Hooks testing in AllocEngine6
  849. ///
  850. /// It features a couple of callout functions and buffers to store
  851. /// the data that is accessible via callouts.
  852. class HookAllocEngine6Test : public AllocEngine6Test {
  853. public:
  854. HookAllocEngine6Test() {
  855. resetCalloutBuffers();
  856. }
  857. virtual ~HookAllocEngine6Test() {
  858. HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts(
  859. "lease6_select");
  860. }
  861. /// @brief clears out buffers, so callouts can store received arguments
  862. void resetCalloutBuffers() {
  863. callback_name_ = string("");
  864. callback_subnet6_.reset();
  865. callback_fake_allocation_ = false;
  866. callback_lease6_.reset();
  867. callback_argument_names_.clear();
  868. callback_addr_original_ = IOAddress("::");
  869. callback_addr_updated_ = IOAddress("::");
  870. }
  871. /// callback that stores received callout name and received values
  872. static int
  873. lease6_select_callout(CalloutHandle& callout_handle) {
  874. callback_name_ = string("lease6_select");
  875. callout_handle.getArgument("subnet6", callback_subnet6_);
  876. callout_handle.getArgument("fake_allocation", callback_fake_allocation_);
  877. callout_handle.getArgument("lease6", callback_lease6_);
  878. callback_addr_original_ = callback_lease6_->addr_;
  879. callback_argument_names_ = callout_handle.getArgumentNames();
  880. return (0);
  881. }
  882. /// callback that overrides the lease with different values
  883. static int
  884. lease6_select_different_callout(CalloutHandle& callout_handle) {
  885. // Let's call the basic callout, so it can record all parameters
  886. lease6_select_callout(callout_handle);
  887. // Now we need to tweak the least a bit
  888. Lease6Ptr lease;
  889. callout_handle.getArgument("lease6", lease);
  890. callback_addr_updated_ = addr_override_;
  891. lease->addr_ = callback_addr_updated_;
  892. lease->t1_ = t1_override_;
  893. lease->t2_ = t2_override_;
  894. lease->preferred_lft_ = pref_override_;
  895. lease->valid_lft_ = valid_override_;
  896. return (0);
  897. }
  898. // Values to be used in callout to override lease6 content
  899. static const IOAddress addr_override_;
  900. static const uint32_t t1_override_;
  901. static const uint32_t t2_override_;
  902. static const uint32_t pref_override_;
  903. static const uint32_t valid_override_;
  904. // Callback will store original and overridden values here
  905. static IOAddress callback_addr_original_;
  906. static IOAddress callback_addr_updated_;
  907. // Buffers (callback will store received values here)
  908. static string callback_name_;
  909. static Subnet6Ptr callback_subnet6_;
  910. static Lease6Ptr callback_lease6_;
  911. static bool callback_fake_allocation_;
  912. static vector<string> callback_argument_names_;
  913. };
  914. // For some reason intialization within a class makes the linker confused.
  915. // linker complains about undefined references if they are defined within
  916. // the class declaration.
  917. const IOAddress HookAllocEngine6Test::addr_override_("2001:db8::abcd");
  918. const uint32_t HookAllocEngine6Test::t1_override_ = 6000;
  919. const uint32_t HookAllocEngine6Test::t2_override_ = 7000;
  920. const uint32_t HookAllocEngine6Test::pref_override_ = 8000;
  921. const uint32_t HookAllocEngine6Test::valid_override_ = 9000;
  922. IOAddress HookAllocEngine6Test::callback_addr_original_("::");
  923. IOAddress HookAllocEngine6Test::callback_addr_updated_("::");
  924. string HookAllocEngine6Test::callback_name_;
  925. Subnet6Ptr HookAllocEngine6Test::callback_subnet6_;
  926. Lease6Ptr HookAllocEngine6Test::callback_lease6_;
  927. bool HookAllocEngine6Test::callback_fake_allocation_;
  928. vector<string> HookAllocEngine6Test::callback_argument_names_;
  929. // This test checks if the lease6_select callout is executed and expected
  930. // parameters as passed.
  931. TEST_F(HookAllocEngine6Test, lease6_select) {
  932. // Note: The following order is working as expected:
  933. // 1. create AllocEngine (that register hook points)
  934. // 2. call loadLibraries()
  935. //
  936. // This order, however, causes segfault in HooksManager
  937. // 1. call loadLibraries()
  938. // 2. create AllocEngine (that register hook points)
  939. // Create allocation engine (hook names are registered in its ctor)
  940. boost::scoped_ptr<AllocEngine> engine;
  941. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  942. ASSERT_TRUE(engine);
  943. // Initialize Hooks Manager
  944. vector<string> libraries; // no libraries at this time
  945. HooksManager::loadLibraries(libraries);
  946. // Install pkt6_receive_callout
  947. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  948. "lease6_select", lease6_select_callout));
  949. CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
  950. Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
  951. false, false, "",
  952. false, callout_handle);
  953. // Check that we got a lease
  954. ASSERT_TRUE(lease);
  955. // Do all checks on the lease
  956. checkLease6(lease);
  957. // Check that the lease is indeed in LeaseMgr
  958. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
  959. ASSERT_TRUE(from_mgr);
  960. // Check that callouts were indeed called
  961. EXPECT_EQ("lease6_select", callback_name_);
  962. // Now check that the lease in LeaseMgr has the same parameters
  963. ASSERT_TRUE(callback_lease6_);
  964. detailCompareLease(callback_lease6_, from_mgr);
  965. ASSERT_TRUE(callback_subnet6_);
  966. EXPECT_EQ(subnet_->toText(), callback_subnet6_->toText());
  967. EXPECT_FALSE(callback_fake_allocation_);
  968. // Check if all expected parameters are reported. It's a bit tricky, because
  969. // order may be different. If the test starts failing, because someone tweaked
  970. // hooks engine, we'll have to implement proper vector matching (ignoring order)
  971. vector<string> expected_argument_names;
  972. expected_argument_names.push_back("fake_allocation");
  973. expected_argument_names.push_back("lease6");
  974. expected_argument_names.push_back("subnet6");
  975. sort(callback_argument_names_.begin(), callback_argument_names_.end());
  976. sort(expected_argument_names.begin(), expected_argument_names.end());
  977. EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
  978. }
  979. // This test checks if lease6_select callout is able to override the values
  980. // in a lease6.
  981. TEST_F(HookAllocEngine6Test, change_lease6_select) {
  982. // Make sure that the overridden values are different than the ones from
  983. // subnet originally used to create the lease
  984. ASSERT_NE(t1_override_, subnet_->getT1());
  985. ASSERT_NE(t2_override_, subnet_->getT2());
  986. ASSERT_NE(pref_override_, subnet_->getPreferred());
  987. ASSERT_NE(valid_override_, subnet_->getValid());
  988. ASSERT_FALSE(subnet_->inRange(addr_override_));
  989. // Create allocation engine (hook names are registered in its ctor)
  990. boost::scoped_ptr<AllocEngine> engine;
  991. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  992. ASSERT_TRUE(engine);
  993. // Initialize Hooks Manager
  994. vector<string> libraries; // no libraries at this time
  995. HooksManager::loadLibraries(libraries);
  996. // Install a callout
  997. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  998. "lease6_select", lease6_select_different_callout));
  999. // Normally, dhcpv6_srv would passed the handle when calling allocateAddress6,
  1000. // but in tests we need to create it on our own.
  1001. CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
  1002. // Call allocateAddress6. Callouts should be triggered here.
  1003. Lease6Ptr lease = engine->allocateAddress6(subnet_, duid_, iaid_, IOAddress("::"),
  1004. false, false, "",
  1005. false, callout_handle);
  1006. // Check that we got a lease
  1007. ASSERT_TRUE(lease);
  1008. // See if the values overridden by callout are there
  1009. EXPECT_TRUE(lease->addr_.equals(addr_override_));
  1010. EXPECT_EQ(t1_override_, lease->t1_);
  1011. EXPECT_EQ(t2_override_, lease->t2_);
  1012. EXPECT_EQ(pref_override_, lease->preferred_lft_);
  1013. EXPECT_EQ(valid_override_, lease->valid_lft_);
  1014. // Now check if the lease is in the database
  1015. Lease6Ptr from_mgr = LeaseMgrFactory::instance().getLease6(lease->addr_);
  1016. ASSERT_TRUE(from_mgr);
  1017. // Check if values in the database are overridden
  1018. EXPECT_TRUE(from_mgr->addr_.equals(addr_override_));
  1019. EXPECT_EQ(t1_override_, from_mgr->t1_);
  1020. EXPECT_EQ(t2_override_, from_mgr->t2_);
  1021. EXPECT_EQ(pref_override_, from_mgr->preferred_lft_);
  1022. EXPECT_EQ(valid_override_, from_mgr->valid_lft_);
  1023. }
  1024. /// @brief helper class used in Hooks testing in AllocEngine4
  1025. ///
  1026. /// It features a couple of callout functions and buffers to store
  1027. /// the data that is accessible via callouts.
  1028. class HookAllocEngine4Test : public AllocEngine4Test {
  1029. public:
  1030. HookAllocEngine4Test() {
  1031. resetCalloutBuffers();
  1032. }
  1033. virtual ~HookAllocEngine4Test() {
  1034. HooksManager::preCalloutsLibraryHandle().deregisterAllCallouts(
  1035. "lease4_select");
  1036. }
  1037. /// @brief clears out buffers, so callouts can store received arguments
  1038. void resetCalloutBuffers() {
  1039. callback_name_ = string("");
  1040. callback_subnet4_.reset();
  1041. callback_fake_allocation_ = false;
  1042. callback_lease4_.reset();
  1043. callback_argument_names_.clear();
  1044. callback_addr_original_ = IOAddress("::");
  1045. callback_addr_updated_ = IOAddress("::");
  1046. }
  1047. /// callback that stores received callout name and received values
  1048. static int
  1049. lease4_select_callout(CalloutHandle& callout_handle) {
  1050. callback_name_ = string("lease4_select");
  1051. callout_handle.getArgument("subnet4", callback_subnet4_);
  1052. callout_handle.getArgument("fake_allocation", callback_fake_allocation_);
  1053. callout_handle.getArgument("lease4", callback_lease4_);
  1054. callback_addr_original_ = callback_lease4_->addr_;
  1055. callback_argument_names_ = callout_handle.getArgumentNames();
  1056. return (0);
  1057. }
  1058. /// callback that overrides the lease with different values
  1059. static int
  1060. lease4_select_different_callout(CalloutHandle& callout_handle) {
  1061. // Let's call the basic callout, so it can record all parameters
  1062. lease4_select_callout(callout_handle);
  1063. // Now we need to tweak the least a bit
  1064. Lease4Ptr lease;
  1065. callout_handle.getArgument("lease4", lease);
  1066. callback_addr_updated_ = addr_override_;
  1067. lease->addr_ = callback_addr_updated_;
  1068. lease->t1_ = t1_override_;
  1069. lease->t2_ = t2_override_;
  1070. lease->valid_lft_ = valid_override_;
  1071. return (0);
  1072. }
  1073. // Values to be used in callout to override lease4 content
  1074. static const IOAddress addr_override_;
  1075. static const uint32_t t1_override_;
  1076. static const uint32_t t2_override_;
  1077. static const uint32_t valid_override_;
  1078. // Callback will store original and overridden values here
  1079. static IOAddress callback_addr_original_;
  1080. static IOAddress callback_addr_updated_;
  1081. // Buffers (callback will store received values here)
  1082. static string callback_name_;
  1083. static Subnet4Ptr callback_subnet4_;
  1084. static Lease4Ptr callback_lease4_;
  1085. static bool callback_fake_allocation_;
  1086. static vector<string> callback_argument_names_;
  1087. };
  1088. // For some reason intialization within a class makes the linker confused.
  1089. // linker complains about undefined references if they are defined within
  1090. // the class declaration.
  1091. const IOAddress HookAllocEngine4Test::addr_override_("192.0.3.1");
  1092. const uint32_t HookAllocEngine4Test::t1_override_ = 4000;
  1093. const uint32_t HookAllocEngine4Test::t2_override_ = 7000;
  1094. const uint32_t HookAllocEngine4Test::valid_override_ = 9000;
  1095. IOAddress HookAllocEngine4Test::callback_addr_original_("::");
  1096. IOAddress HookAllocEngine4Test::callback_addr_updated_("::");
  1097. string HookAllocEngine4Test::callback_name_;
  1098. Subnet4Ptr HookAllocEngine4Test::callback_subnet4_;
  1099. Lease4Ptr HookAllocEngine4Test::callback_lease4_;
  1100. bool HookAllocEngine4Test::callback_fake_allocation_;
  1101. vector<string> HookAllocEngine4Test::callback_argument_names_;
  1102. // This test checks if the lease4_select callout is executed and expected
  1103. // parameters as passed.
  1104. TEST_F(HookAllocEngine4Test, lease4_select) {
  1105. // Note: The following order is working as expected:
  1106. // 1. create AllocEngine (that register hook points)
  1107. // 2. call loadLibraries()
  1108. //
  1109. // This order, however, causes segfault in HooksManager
  1110. // 1. call loadLibraries()
  1111. // 2. create AllocEngine (that register hook points)
  1112. // Create allocation engine (hook names are registered in its ctor)
  1113. boost::scoped_ptr<AllocEngine> engine;
  1114. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  1115. ASSERT_TRUE(engine);
  1116. // Initialize Hooks Manager
  1117. vector<string> libraries; // no libraries at this time
  1118. HooksManager::loadLibraries(libraries);
  1119. // Install pkt4_receive_callout
  1120. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  1121. "lease4_select", lease4_select_callout));
  1122. CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
  1123. Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_,
  1124. IOAddress("0.0.0.0"),
  1125. false, callout_handle);
  1126. // Check that we got a lease
  1127. ASSERT_TRUE(lease);
  1128. // Do all checks on the lease
  1129. checkLease4(lease);
  1130. // Check that the lease is indeed in LeaseMgr
  1131. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
  1132. ASSERT_TRUE(from_mgr);
  1133. // Check that callouts were indeed called
  1134. EXPECT_EQ("lease4_select", callback_name_);
  1135. // Now check that the lease in LeaseMgr has the same parameters
  1136. ASSERT_TRUE(callback_lease4_);
  1137. detailCompareLease(callback_lease4_, from_mgr);
  1138. ASSERT_TRUE(callback_subnet4_);
  1139. EXPECT_EQ(subnet_->toText(), callback_subnet4_->toText());
  1140. EXPECT_EQ(callback_fake_allocation_, false);
  1141. // Check if all expected parameters are reported. It's a bit tricky, because
  1142. // order may be different. If the test starts failing, because someone tweaked
  1143. // hooks engine, we'll have to implement proper vector matching (ignoring order)
  1144. vector<string> expected_argument_names;
  1145. expected_argument_names.push_back("fake_allocation");
  1146. expected_argument_names.push_back("lease4");
  1147. expected_argument_names.push_back("subnet4");
  1148. EXPECT_TRUE(callback_argument_names_ == expected_argument_names);
  1149. }
  1150. // This test checks if lease4_select callout is able to override the values
  1151. // in a lease4.
  1152. TEST_F(HookAllocEngine4Test, change_lease4_select) {
  1153. // Make sure that the overridden values are different than the ones from
  1154. // subnet originally used to create the lease
  1155. ASSERT_NE(t1_override_, subnet_->getT1());
  1156. ASSERT_NE(t2_override_, subnet_->getT2());
  1157. ASSERT_NE(valid_override_, subnet_->getValid());
  1158. ASSERT_FALSE(subnet_->inRange(addr_override_));
  1159. // Create allocation engine (hook names are registered in its ctor)
  1160. boost::scoped_ptr<AllocEngine> engine;
  1161. ASSERT_NO_THROW(engine.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
  1162. ASSERT_TRUE(engine);
  1163. // Initialize Hooks Manager
  1164. vector<string> libraries; // no libraries at this time
  1165. HooksManager::loadLibraries(libraries);
  1166. // Install a callout
  1167. EXPECT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout(
  1168. "lease4_select", lease4_select_different_callout));
  1169. // Normally, dhcpv4_srv would passed the handle when calling allocateAddress4,
  1170. // but in tests we need to create it on our own.
  1171. CalloutHandlePtr callout_handle = HooksManager::createCalloutHandle();
  1172. // Call allocateAddress4. Callouts should be triggered here.
  1173. Lease4Ptr lease = engine->allocateAddress4(subnet_, clientid_, hwaddr_, IOAddress("0.0.0.0"),
  1174. false, callout_handle);
  1175. // Check that we got a lease
  1176. ASSERT_TRUE(lease);
  1177. // See if the values overridden by callout are there
  1178. EXPECT_TRUE(lease->addr_.equals(addr_override_));
  1179. EXPECT_EQ(t1_override_, lease->t1_);
  1180. EXPECT_EQ(t2_override_, lease->t2_);
  1181. EXPECT_EQ(valid_override_, lease->valid_lft_);
  1182. // Now check if the lease is in the database
  1183. Lease4Ptr from_mgr = LeaseMgrFactory::instance().getLease4(lease->addr_);
  1184. ASSERT_TRUE(from_mgr);
  1185. // Check if values in the database are overridden
  1186. EXPECT_TRUE(from_mgr->addr_.equals(addr_override_));
  1187. EXPECT_EQ(t1_override_, from_mgr->t1_);
  1188. EXPECT_EQ(t2_override_, from_mgr->t2_);
  1189. EXPECT_EQ(valid_override_, from_mgr->valid_lft_);
  1190. }
  1191. }; // End of anonymous namespace