Browse Source

[2324] Documentation updated, {Hashed,Random}Allocator skeletons implemented.

Tomek Mrugalski 12 years ago
parent
commit
cb330a0684
3 changed files with 136 additions and 27 deletions
  1. 26 2
      src/lib/dhcp/alloc_engine.cc
  2. 108 23
      src/lib/dhcp/alloc_engine.h
  3. 2 2
      src/lib/dhcp/tests/alloc_engine_unittest.cc

+ 26 - 2
src/lib/dhcp/alloc_engine.cc

@@ -113,6 +113,32 @@ AllocEngine::IterativeAllocator::pickAddress(const Subnet6Ptr& subnet,
     return (next);
 }
 
+AllocEngine::HashedAllocator::HashedAllocator()
+    :Allocator() {
+    isc_throw(NotImplemented, "Hashed allocator is not implemented");
+}
+
+
+isc::asiolink::IOAddress
+AllocEngine::HashedAllocator::pickAddress(const Subnet6Ptr&,
+                                             const DuidPtr&,
+                                             const IOAddress&) {
+    isc_throw(NotImplemented, "Hashed allocator is not implemented");
+}
+
+AllocEngine::RandomAllocator::RandomAllocator()
+    :Allocator() {
+    isc_throw(NotImplemented, "Random allocator is not implemented");
+}
+
+
+isc::asiolink::IOAddress
+AllocEngine::RandomAllocator::pickAddress(const Subnet6Ptr&,
+                                             const DuidPtr&,
+                                             const IOAddress&) {
+    isc_throw(NotImplemented, "Random allocator is not implemented");
+}
+
 
 AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
     :attempts_(attempts) {
@@ -120,14 +146,12 @@ AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
     case ALLOC_ITERATIVE:
         allocator_ = new IterativeAllocator();
         break;
-#if 0
     case ALLOC_HASHED:
         allocator_ = new HashedAllocator();
         break;
     case ALLOC_RANDOM:
         allocator_ = new RandomAllocator();
         break;
-#endif
 
     default:
         isc_throw(BadValue, "Invalid/unsupported allocation algorithm");

+ 108 - 23
src/lib/dhcp/alloc_engine.h

@@ -44,51 +44,113 @@ AllocFailed(const char* file, size_t line, const char* what)
 /// This class represents DHCP allocation engine. It is responsible
 /// for picking subnets, choosing and allocating a lease, extending,
 /// renewing, releasing and possibly expiring leases.
-
+///
+/// @todo: Does not handle out of leases well
+/// @todo: Does not handle out of allocation attempts well
 class AllocEngine : public boost::noncopyable {
 protected:
 
+    /// @brief base class for all address/prefix allocation algorithms
+    ///
+    /// This is an abstract class that should not be used directly, but rather
+    /// specialized implementations should be used instead.
     class Allocator {
     public:
+
+        /// @brief picks one address out of available pools in a given subnet
+        ///
+        /// This method returns one address from the available pools in the
+        /// specified subnet. It should not check if the address is used or
+        /// reserved - AllocEngine will check that and will call pickAddress
+        /// again if necessary. The number of times this method is called will
+        /// increase as the number of available leases will decrease.
         virtual isc::asiolink::IOAddress
             pickAddress(const Subnet6Ptr& subnet,
                         const DuidPtr& duid,
                         const isc::asiolink::IOAddress& hint) = 0;
     protected:
+        /// @brief protected constructor
+        ///
+        /// Prevents anyone from attempting to instantiate Allocator objects
+        /// directly. Derived classes should be used instead.
         Allocator() {
         }
     };
 
+    /// @brief Address/prefix allocator that iterates over all addresses
+    ///
+    /// This class implements iterative algorithm that returns all addresses in
+    /// a pool iteratively, one after another.
     class IterativeAllocator : public Allocator {
     public:
+
+        /// @brief default constructor
+        ///
+        /// Does not do anything
         IterativeAllocator();
+
+        /// @brief returns the next address from pools in a subnet
+        ///
+        /// @param subnet next address will be returned from pool of that subnet
+        /// @param duid Client's DUID (ignored)
+        /// @param hint client's hint (ignored)
+        /// @return the next address
         virtual isc::asiolink::IOAddress
             pickAddress(const Subnet6Ptr& subnet,
                         const DuidPtr& duid,
                         const isc::asiolink::IOAddress& hint);
     private:
+
+        /// @brief returns an address by one
+        /// @param addr address to be increased
+        /// @return address increased by one
         isc::asiolink::IOAddress increaseAddress(const isc::asiolink::IOAddress& addr);
 
     };
 
-#if 0
-    class HashedAllocator {
+    /// @brief Address/prefix allocator that gets an address based on a hash
+    ///
+    /// @todo: This is a skeleton class for now and is missing implementation.
+    class HashedAllocator : public Allocator {
     public:
-        IterativeAllocator(unsigned int attempts);
-        virtual isc::asiolink::IOAddress allocateAddress(const Subnet6Ptr& subnet,
-                                                         const DuidPtr& duid,
-                                                         const DUIOAddress& hint);
-    }
 
-    class RandomAllocator() {
+        /// @brief default constructor (does nothing)
+        HashedAllocator();
+
+        /// @brief returns an address based on hash calculated from client's DUID.
+        ///
+        /// @todo: Implement this method
+        ///
+        /// @param subnet an address will be picked from pool of that subnet
+        /// @param duid Client's DUID
+        /// @param hint a hint (last address that was picked)
+        /// @return selected address
+        virtual isc::asiolink::IOAddress pickAddress(const Subnet6Ptr& subnet,
+                                                     const DuidPtr& duid,
+                                                     const isc::asiolink::IOAddress& hint);
+    };
+
+    /// @brief Random allocator that picks address randomly
+    ///
+    /// @todo: This is a skeleton class for now and is missing implementation.
+    class RandomAllocator : public Allocator {
     public:
-        IterativeAllocator(unsigned int attempts);
+
+        /// @brief default constructor (does nothing)
+        RandomAllocator();
+
+        /// @brief returns an random address from pool of specified subnet
+        ///
+        /// @todo: Implement this method
+        ///
+        /// @param subnet an address will be picked from pool of that subnet
+        /// @param duid Client's DUID (ignored)
+        /// @param hint the last address that was picked (ignored)
+        /// @return a random address from the pool
         virtual isc::asiolink::IOAddress
-        allocateAddress(const Subnet6Ptr& subnet,
-                        const DuidPtr& duid,
-                        const DUIOAddress& hint);
-    }
-#endif
+        pickAddress(const Subnet6Ptr& subnet, const DuidPtr& duid,
+                    const isc::asiolink::IOAddress& hint);
+    };
 
     public:
 
@@ -108,8 +170,22 @@ protected:
     /// old or create new DUID.
     ///
     /// @param engine_type selects allocation algorithm
+    /// @param attempts number of attempts for each lease allocation before
+    ///        we give up (0 mean unlimited)
     AllocEngine(AllocType engine_type, unsigned int attempts);
 
+    /// @brief Allocates an IPv6 lease
+    ///
+    /// This method uses currently selected allocator to pick an address from
+    /// specified subnet, creates a lease for that address and then inserts
+    /// it into LeaseMgr (if this allocation is not fake).
+    ///
+    /// @param subnet subnet the allocation should come from
+    /// @param duid Client'd DUID
+    /// @param iaid iaid field from the IA_NA container that client sent
+    /// @param hint a hint that the client provided
+    /// @param fake is this real (REQUEST) or fake (SOLICIT) allocation
+    /// @return Allocated IPv6 lease (or NULL if allocation failed)
     Lease6Ptr
     allocateAddress6(const Subnet6Ptr& subnet,
                      const DuidPtr& duid,
@@ -120,19 +196,28 @@ protected:
     /// @brief Destructor. Used during DHCPv6 service shutdown.
     virtual ~AllocEngine();
 private:
-    isc::asiolink::IOAddress
-    allocateAddress(const Subnet6Ptr& subnet,
-                    const DuidPtr& duid,
-                    const isc::asiolink::IOAddress& hint);
 
-    Lease6Ptr createLease(const Subnet6Ptr& subnet,
-                          const DuidPtr& duid,
-                          uint32_t iaid,
-                          const isc::asiolink::IOAddress& addr,
+    /// @brief creates a lease and inserts it in LeaseMgr if necessary
+    ///
+    /// Creates a lease based on specified parameters and tries to insert it
+    /// into the database. That may fail in some cases, i.e. when there is another
+    /// allocation process and we lost a race to a specific lease.
+    ///
+    /// @param subnet subnet the lease is allocated from
+    /// @param duid client's DUID
+    /// @param iaid IAID from the IA_NA container the client sent to us
+    /// @param addr an address that was selected and is confirmed to be available
+    /// @param fake is this SOLICIT (true) or a real/REQUEST allocation (false)?
+    /// @return allocated lease (or NULL in the unlikely case of the lease just
+    ///        becomed unavailable)
+    Lease6Ptr createLease(const Subnet6Ptr& subnet, const DuidPtr& duid,
+                          uint32_t iaid, const isc::asiolink::IOAddress& addr,
                           bool fake = false);
 
+    /// @brief a pointer to currently used allocator
     Allocator* allocator_;
 
+    /// @brief number of attempts before we give up lease allocation (0=unlimited)
     unsigned int attempts_;
 };
 

+ 2 - 2
src/lib/dhcp/tests/alloc_engine_unittest.cc

@@ -96,8 +96,8 @@ TEST_F(AllocEngineTest, constructor) {
     AllocEngine* x = NULL;
 
     // Hashed and random allocators are not supported yet
-    ASSERT_THROW(x = new AllocEngine(AllocEngine::ALLOC_HASHED, 5), BadValue);
-    ASSERT_THROW(x = new AllocEngine(AllocEngine::ALLOC_RANDOM, 5), BadValue);
+    ASSERT_THROW(x = new AllocEngine(AllocEngine::ALLOC_HASHED, 5), NotImplemented);
+    ASSERT_THROW(x = new AllocEngine(AllocEngine::ALLOC_RANDOM, 5), NotImplemented);
 
     ASSERT_NO_THROW(x = new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100));