alloc_engine_unittest.cc 70 KB

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