Browse Source

[3149] getAllocator() implemented

Tomek Mrugalski 11 years ago
parent
commit
d7d74b3493

+ 47 - 12
src/lib/dhcpsrv/alloc_engine.cc

@@ -177,23 +177,44 @@ AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts,
                          bool ipv6)
     :attempts_(attempts) {
 
-    Lease::Type pool_type = ipv6?Lease::TYPE_NA:Lease::TYPE_V4;
+    Lease::Type basic_type = ipv6?Lease::TYPE_NA:Lease::TYPE_V4;
 
+    // Initalize normal address allocators
     switch (engine_type) {
     case ALLOC_ITERATIVE:
-        allocator_.reset(new IterativeAllocator(pool_type));
+        allocators_[basic_type] = AllocatorPtr(new IterativeAllocator(basic_type));
         break;
     case ALLOC_HASHED:
-        allocator_.reset(new HashedAllocator(pool_type));
+        allocators_[basic_type] = AllocatorPtr(new HashedAllocator(basic_type));
         break;
     case ALLOC_RANDOM:
-        allocator_.reset(new RandomAllocator(pool_type));
+        allocators_[basic_type] = AllocatorPtr(new RandomAllocator(basic_type));
         break;
-
     default:
         isc_throw(BadValue, "Invalid/unsupported allocation algorithm");
     }
 
+    // If this is IPv6 allocation engine, initalize also temporary addrs
+    // and prefixes
+    if (ipv6) {
+        switch (engine_type) {
+        case ALLOC_ITERATIVE:
+            allocators_[Lease::TYPE_TA] = AllocatorPtr(new IterativeAllocator(Lease::TYPE_TA));
+            allocators_[Lease::TYPE_PD] = AllocatorPtr(new IterativeAllocator(Lease::TYPE_PD));
+            break;
+        case ALLOC_HASHED:
+            allocators_[Lease::TYPE_TA] = AllocatorPtr(new HashedAllocator(Lease::TYPE_TA));
+            allocators_[Lease::TYPE_PD] = AllocatorPtr(new HashedAllocator(Lease::TYPE_PD));
+            break;
+        case ALLOC_RANDOM:
+            allocators_[Lease::TYPE_TA] = AllocatorPtr(new RandomAllocator(Lease::TYPE_TA));
+            allocators_[Lease::TYPE_PD] = AllocatorPtr(new RandomAllocator(Lease::TYPE_PD));
+            break;
+        default:
+            isc_throw(BadValue, "Invalid/unsupported allocation algorithm");
+        }
+    }
+
     // Register hook points
     hook_index_lease4_select_ = Hooks.hook_index_lease4_select_;
     hook_index_lease6_select_ = Hooks.hook_index_lease6_select_;
@@ -212,10 +233,11 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
                               const isc::hooks::CalloutHandlePtr& callout_handle) {
 
     try {
-        // That check is not necessary. We create allocator in AllocEngine
-        // constructor
-        if (!allocator_) {
-            isc_throw(InvalidOperation, "No allocator selected");
+        AllocatorPtr allocator = getAllocator(type);
+
+        if (!allocator) {
+            isc_throw(InvalidOperation, "No allocator specified for "
+                      << Lease6::typeToText(type));
         }
 
         if (!subnet) {
@@ -296,7 +318,7 @@ AllocEngine::allocateAddress6(const Subnet6Ptr& subnet,
 
         unsigned int i = attempts_;
         do {
-            IOAddress candidate = allocator_->pickAddress(subnet, duid, hint);
+            IOAddress candidate = allocator->pickAddress(subnet, duid, hint);
 
             /// @todo: check if the address is reserved once we have host support
             /// implemented
@@ -366,9 +388,12 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
     old_lease.reset();
 
     try {
+
+        AllocatorPtr allocator = getAllocator(Lease::TYPE_V4);
+
         // Allocator is always created in AllocEngine constructor and there is
         // currently no other way to set it, so that check is not really necessary.
-        if (!allocator_) {
+        if (!allocator) {
             isc_throw(InvalidOperation, "No allocator selected");
         }
 
@@ -467,7 +492,7 @@ AllocEngine::allocateAddress4(const SubnetPtr& subnet,
 
         unsigned int i = attempts_;
         do {
-            IOAddress candidate = allocator_->pickAddress(subnet, clientid, hint);
+            IOAddress candidate = allocator->pickAddress(subnet, clientid, hint);
 
             /// @todo: check if the address is reserved once we have host support
             /// implemented
@@ -923,6 +948,16 @@ Lease4Ptr AllocEngine::createLease4(const SubnetPtr& subnet,
     }
 }
 
+AllocEngine::AllocatorPtr AllocEngine::getAllocator(Lease::Type type) {
+    std::map<Lease::Type, AllocatorPtr>::const_iterator alloc = allocators_.find(type);
+
+    if (alloc == allocators_.end()) {
+        isc_throw(BadValue, "No allocator initialized for pool type "
+                  << Lease::typeToText(type));
+    }
+    return (alloc->second);
+}
+
 AllocEngine::~AllocEngine() {
     // no need to delete allocator. smart_ptr will do the trick for us
 }

+ 15 - 1
src/lib/dhcpsrv/alloc_engine.h

@@ -25,6 +25,8 @@
 #include <boost/shared_ptr.hpp>
 #include <boost/noncopyable.hpp>
 
+#include <map>
+
 namespace isc {
 namespace dhcp {
 
@@ -94,6 +96,9 @@ protected:
         Lease::Type pool_type_;
     };
 
+    /// defines a pointer to allocator
+    typedef boost::shared_ptr<Allocator> AllocatorPtr;
+
     /// @brief Address/prefix allocator that iterates over all addresses
     ///
     /// This class implements iterative algorithm that returns all addresses in
@@ -324,6 +329,12 @@ protected:
                      bool fake_allocation,
                      const isc::hooks::CalloutHandlePtr& callout_handle);
 
+    /// @brief returns allocator for a given pool type
+    /// @param type type of pool (V4, IA, TA or PD)
+    /// @throw BadValue if allocator for a given type is missing
+    /// @return pointer to allocator handing a given resource types
+    AllocatorPtr getAllocator(Lease::Type type);
+
     /// @brief Destructor. Used during DHCPv6 service shutdown.
     virtual ~AllocEngine();
 private:
@@ -456,7 +467,10 @@ private:
                                 bool fake_allocation = false);
 
     /// @brief a pointer to currently used allocator
-    boost::shared_ptr<Allocator> allocator_;
+    ///
+    /// For IPv4, there will be only one allocator: TYPE_V4
+    /// For IPv6, there will be 3 allocators: TYPE_NA, TYPE_TA, TYPE_PD
+    std::map<Lease::Type, AllocatorPtr> allocators_;
 
     /// @brief number of attempts before we give up lease allocation (0=unlimited)
     unsigned int attempts_;

+ 2 - 0
src/lib/dhcpsrv/lease.cc

@@ -32,6 +32,8 @@ Lease::Lease(const isc::asiolink::IOAddress& addr, uint32_t t1, uint32_t t2,
 std::string
 Lease::typeToText(Lease::Type type) {
    switch (type) {
+   case Lease::TYPE_V4:
+       return string("V4");
    case Lease::TYPE_NA:
        return string("IA_NA");
    case Lease::TYPE_TA:

+ 42 - 3
src/lib/dhcpsrv/tests/alloc_engine_unittest.cc

@@ -64,6 +64,7 @@ public:
     // Expose internal classes for testing purposes
     using AllocEngine::Allocator;
     using AllocEngine::IterativeAllocator;
+    using AllocEngine::getAllocator;
 };
 
 /// @brief Used in Allocation Engine tests for IPv6
@@ -209,8 +210,8 @@ public:
     Lease4Ptr old_lease_;     ///< Holds previous instance of the lease.
 };
 
-// This test checks if the Allocation Engine can be instantiated and that it
-// parses parameters string properly.
+// This test checks if the v6 Allocation Engine can be instantiated, parses
+// parameters string and allocators are created.
 TEST_F(AllocEngine6Test, constructor) {
     boost::scoped_ptr<AllocEngine> x;
 
@@ -218,7 +219,19 @@ TEST_F(AllocEngine6Test, constructor) {
     ASSERT_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_HASHED, 5)), NotImplemented);
     ASSERT_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_RANDOM, 5)), NotImplemented);
 
-    ASSERT_NO_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100)));
+    ASSERT_NO_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100, true)));
+
+    // Check that allocator for normal addresses is created
+    ASSERT_TRUE(x->getAllocator(Lease::TYPE_NA));
+
+    // Check that allocator for temporary address is created
+    ASSERT_TRUE(x->getAllocator(Lease::TYPE_TA));
+
+    // Check that allocator for prefixes is created
+    ASSERT_TRUE(x->getAllocator(Lease::TYPE_PD));
+
+    // There should be no V4 allocator
+    EXPECT_THROW(x->getAllocator(Lease::TYPE_V4), BadValue);
 }
 
 // This test checks if the simple allocation can succeed
@@ -632,6 +645,32 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) {
 
 // --- IPv4 ---
 
+// This test checks if the v4 Allocation Engine can be instantiated, parses
+// parameters string and allocators are created.
+TEST_F(AllocEngine4Test, constructor) {
+    boost::scoped_ptr<AllocEngine> x;
+
+    // Hashed and random allocators are not supported yet
+    ASSERT_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_HASHED, 5, false)),
+                 NotImplemented);
+    ASSERT_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_RANDOM, 5, false)),
+                 NotImplemented);
+
+    // Create V4 (ipv6=false) Allocation Engine that will try at most
+    // 100 attempts to pick up a lease
+    ASSERT_NO_THROW(x.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100,
+                                            false)));
+
+    // There should be V4 allocator
+    ASSERT_TRUE(x->getAllocator(Lease::TYPE_V4));
+
+    // Check that allocators for V6 stuff are not created
+    EXPECT_THROW(x->getAllocator(Lease::TYPE_NA), BadValue);
+    EXPECT_THROW(x->getAllocator(Lease::TYPE_TA), BadValue);
+    EXPECT_THROW(x->getAllocator(Lease::TYPE_PD), BadValue);
+}
+
+
 // This test checks if the simple IPv4 allocation can succeed
 TEST_F(AllocEngine4Test, simpleAlloc4) {
     boost::scoped_ptr<AllocEngine> engine;