Parcourir la source

[3150] First part of prefix pool support

Tomek Mrugalski il y a 11 ans
Parent
commit
154fbc8f1d

+ 6 - 6
src/bin/dhcp6/config_parser.cc

@@ -141,13 +141,13 @@ protected:
     ///
     /// @param addr is the IPv6 prefix of the pool.
     /// @param len is the prefix length.
-    /// @param ptype is the type of IPv6 pool (Pool6::Pool6Type). Note this is
-    /// passed in as an int32_t and cast to Pool6Type to accommodate a
+    /// @param ptype is the type of IPv6 pool (Pool::PoolType). Note this is
+    /// passed in as an int32_t and cast to PoolType to accommodate a
     /// polymorphic interface.
     /// @return returns a PoolPtr to the new Pool4 object.
     PoolPtr poolMaker (IOAddress &addr, uint32_t len, int32_t ptype)
     {
-        return (PoolPtr(new Pool6(static_cast<isc::dhcp::Pool6::Pool6Type>
+        return (PoolPtr(new Pool6(static_cast<isc::dhcp::Pool::PoolType>
                                   (ptype), addr, len)));
     }
 
@@ -155,13 +155,13 @@ protected:
     ///
     /// @param min is the first IPv6 address in the pool.
     /// @param max is the last IPv6 address in the pool.
-    /// @param ptype is the type of IPv6 pool (Pool6::Pool6Type). Note this is
-    /// passed in as an int32_t and cast to Pool6Type to accommodate a
+    /// @param ptype is the type of IPv6 pool (Pool::PoolType). Note this is
+    /// passed in as an int32_t and cast to PoolType to accommodate a
     /// polymorphic interface.
     /// @return returns a PoolPtr to the new Pool4 object.
     PoolPtr poolMaker (IOAddress &min, IOAddress &max, int32_t ptype)
     {
-        return (PoolPtr(new Pool6(static_cast<isc::dhcp::Pool6::Pool6Type>
+        return (PoolPtr(new Pool6(static_cast<isc::dhcp::Pool::PoolType>
                                   (ptype), min, max)));
     }
 };

+ 14 - 14
src/lib/dhcpsrv/alloc_engine.cc

@@ -53,8 +53,8 @@ AllocEngineHooks Hooks;
 namespace isc {
 namespace dhcp {
 
-AllocEngine::IterativeAllocator::IterativeAllocator()
-    :Allocator() {
+AllocEngine::IterativeAllocator::IterativeAllocator(Pool::PoolType lease_type)
+    :Allocator(lease_type) {
 }
 
 isc::asiolink::IOAddress
@@ -94,7 +94,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
     // Let's get the last allocated address. It is usually set correctly,
     // but there are times when it won't be (like after removing a pool or
     // perhaps restarting the server).
-    IOAddress last = subnet->getLastAllocated();
+    IOAddress last = subnet->getLastAllocated(lease_type_);
 
     const PoolCollection& pools = subnet->getPools();
 
@@ -117,7 +117,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
     if (it == pools.end()) {
         // ok to access first element directly. We checked that pools is non-empty
         IOAddress next = pools[0]->getFirstAddress();
-        subnet->setLastAllocated(next);
+        subnet->setLastAllocated(next, lease_type_);
         return (next);
     }
 
@@ -126,7 +126,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
     IOAddress next = increaseAddress(last); // basically addr++
     if ((*it)->inRange(next)) {
         // the next one is in the pool as well, so we haven't hit pool boundary yet
-        subnet->setLastAllocated(next);
+        subnet->setLastAllocated(next, lease_type_);
         return (next);
     }
 
@@ -136,18 +136,18 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
         // Really out of luck today. That was the last pool. Let's rewind
         // to the beginning.
         next = pools[0]->getFirstAddress();
-        subnet->setLastAllocated(next);
+        subnet->setLastAllocated(next, lease_type_);
         return (next);
     }
 
     // there is a next pool, let's try first address from it
     next = (*it)->getFirstAddress();
-    subnet->setLastAllocated(next);
+    subnet->setLastAllocated(next, lease_type_);
     return (next);
 }
 
-AllocEngine::HashedAllocator::HashedAllocator()
-    :Allocator() {
+AllocEngine::HashedAllocator::HashedAllocator(Pool::PoolType lease_type)
+    :Allocator(lease_type) {
     isc_throw(NotImplemented, "Hashed allocator is not implemented");
 }
 
@@ -159,8 +159,8 @@ AllocEngine::HashedAllocator::pickAddress(const SubnetPtr&,
     isc_throw(NotImplemented, "Hashed allocator is not implemented");
 }
 
-AllocEngine::RandomAllocator::RandomAllocator()
-    :Allocator() {
+AllocEngine::RandomAllocator::RandomAllocator(Pool::PoolType lease_type)
+    :Allocator(lease_type) {
     isc_throw(NotImplemented, "Random allocator is not implemented");
 }
 
@@ -177,13 +177,13 @@ AllocEngine::AllocEngine(AllocType engine_type, unsigned int attempts)
     :attempts_(attempts) {
     switch (engine_type) {
     case ALLOC_ITERATIVE:
-        allocator_ = boost::shared_ptr<Allocator>(new IterativeAllocator());
+        allocator_.reset(new IterativeAllocator(Pool6::TYPE_IA));
         break;
     case ALLOC_HASHED:
-        allocator_ = boost::shared_ptr<Allocator>(new HashedAllocator());
+        allocator_.reset(new HashedAllocator(Pool6::TYPE_IA));
         break;
     case ALLOC_RANDOM:
-        allocator_ = boost::shared_ptr<Allocator>(new RandomAllocator());
+        allocator_.reset(new RandomAllocator(Pool6::TYPE_IA));
         break;
 
     default:

+ 16 - 3
src/lib/dhcpsrv/alloc_engine.h

@@ -77,10 +77,20 @@ protected:
         pickAddress(const SubnetPtr& subnet, const DuidPtr& duid,
                     const isc::asiolink::IOAddress& hint) = 0;
 
+        /// @brief Default constructor.
+        ///
+        /// Specifies which type of leases this allocator will assign
+        Allocator(Pool::PoolType lease_type)
+            :lease_type_(lease_type) {
+        }
+
         /// @brief virtual destructor
         virtual ~Allocator() {
         }
     protected:
+
+        /// @brief defines lease type allocation
+        Pool::PoolType lease_type_;
     };
 
     /// @brief Address/prefix allocator that iterates over all addresses
@@ -95,7 +105,8 @@ protected:
         /// @brief default constructor
         ///
         /// Does not do anything
-        IterativeAllocator();
+        /// @param type - specifies allocation type
+        IterativeAllocator(Pool::PoolType type);
 
         /// @brief returns the next address from pools in a subnet
         ///
@@ -123,7 +134,8 @@ protected:
     public:
 
         /// @brief default constructor (does nothing)
-        HashedAllocator();
+        /// @param type - specifies allocation type
+        HashedAllocator(Pool::PoolType type);
 
         /// @brief returns an address based on hash calculated from client's DUID.
         ///
@@ -145,7 +157,8 @@ protected:
     public:
 
         /// @brief default constructor (does nothing)
-        RandomAllocator();
+        /// @param type - specifies allocation type
+        RandomAllocator(Pool::PoolType type);
 
         /// @brief returns an random address from pool of specified subnet
         ///

+ 2 - 2
src/lib/dhcpsrv/pool.cc

@@ -62,7 +62,7 @@ Pool4::Pool4(const isc::asiolink::IOAddress& prefix,
 }
 
 
-Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
+Pool6::Pool6(PoolType type, const isc::asiolink::IOAddress& first,
              const isc::asiolink::IOAddress& last)
     :Pool(first, last), type_(type) {
 
@@ -93,7 +93,7 @@ Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
     }
 }
 
-Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
+Pool6::Pool6(PoolType type, const isc::asiolink::IOAddress& prefix,
              uint8_t prefix_len, uint8_t delegated_len /* = 128 */)
     :Pool(prefix, IOAddress("::")),
      type_(type), prefix_len_(delegated_len) {

+ 23 - 18
src/lib/dhcpsrv/pool.h

@@ -32,6 +32,25 @@ class Pool {
 
 public:
 
+    /// @brief specifies Pool type
+    ///
+    /// Currently there are 3 pool types defined in DHCPv6:
+    /// - Non-temporary addresses (conveyed in IA_NA)
+    /// - Temporary addresses (conveyed in IA_TA)
+    /// - Delegated Prefixes (conveyed in IA_PD)
+    ///
+    /// The fourth one (TYPE_V4) is used in DHCPv4 use cases when getPool()
+    /// code is shared between v4 and v6 code.
+    ///
+    /// There is a new one being worked on (IA_PA, see draft-ietf-dhc-host-gen-id), but
+    /// support for it is not planned for now.
+    typedef enum {
+        TYPE_IA = 0,
+        TYPE_TA = 1,
+        TYPE_PD = 2,
+        TYPE_V4 = 3
+    }  PoolType;
+
     /// @brief returns Pool-id
     ///
     /// @return pool-id value
@@ -127,20 +146,6 @@ typedef std::vector<Pool4Ptr> Pool4Collection;
 class Pool6 : public Pool {
 public:
 
-    /// @brief specifies Pool type
-    ///
-    /// Currently there are 3 pool types defined in DHCPv6:
-    /// - Non-temporary addresses (conveyed in IA_NA)
-    /// - Temporary addresses (conveyed in IA_TA)
-    /// - Delegated Prefixes (conveyed in IA_PD)
-    /// There is a new one being worked on (IA_PA, see draft-ietf-dhc-host-gen-id), but
-    /// support for it is not planned for now.
-    typedef enum {
-        TYPE_IA,
-        TYPE_TA,
-        TYPE_PD
-    }  Pool6Type;
-
     /// @brief the constructor for Pool6 "min-max" style definition
     ///
     /// @throw BadValue if PD is define (PD can be only prefix/len)
@@ -148,7 +153,7 @@ public:
     /// @param type type of the pool (IA or TA)
     /// @param first the first address in a pool
     /// @param last the last address in a pool
-    Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
+    Pool6(PoolType type, const isc::asiolink::IOAddress& first,
           const isc::asiolink::IOAddress& last);
 
     /// @brief the constructor for Pool6 "prefix/len" style definition
@@ -172,13 +177,13 @@ public:
     /// @param prefix specifies prefix of the pool
     /// @param prefix_len specifies prefix length of the pool
     /// @param delegated_len specifies lenght of the delegated prefixes
-    Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
+    Pool6(PoolType type, const isc::asiolink::IOAddress& prefix,
           uint8_t prefix_len, uint8_t delegated_len = 128);
 
     /// @brief returns pool type
     ///
     /// @return pool type
-    Pool6Type getType() const {
+    PoolType getType() const {
         return (type_);
     }
 
@@ -193,7 +198,7 @@ public:
 
 private:
     /// @brief defines a pool type
-    Pool6Type type_;
+    PoolType type_;
 
     /// @brief Defines prefix length (for TYPE_PD only)
     uint8_t prefix_len_;

+ 39 - 1
src/lib/dhcpsrv/subnet.cc

@@ -30,7 +30,9 @@ Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
                const Triplet<uint32_t>& valid_lifetime)
     :id_(getNextID()), prefix_(prefix), prefix_len_(len), t1_(t1),
      t2_(t2), valid_(valid_lifetime),
-     last_allocated_(lastAddrInPrefix(prefix, len)) {
+     last_allocated_ia_(lastAddrInPrefix(prefix, len)),
+     last_allocated_ta_(lastAddrInPrefix(prefix, len)),
+     last_allocated_pd_(lastAddrInPrefix(prefix, len)) {
     if ((prefix.isV6() && len > 128) ||
         (prefix.isV4() && len > 32)) {
         isc_throw(BadValue, 
@@ -86,6 +88,38 @@ Subnet::getOptionDescriptor(const std::string& option_space,
     return (*range.first);
 }
 
+isc::asiolink::IOAddress Subnet::getLastAllocated(Pool::PoolType type) const {
+    switch (type) {
+    case Pool::TYPE_V4:
+    case Pool::TYPE_IA:
+        return last_allocated_ia_;
+    case Pool::TYPE_TA:
+        return last_allocated_ta_;
+    case Pool::TYPE_PD:
+        return last_allocated_pd_;
+    default:
+        isc_throw(BadValue, "Pool type " << type << " not supported");
+    }
+}
+
+void Subnet::setLastAllocated(const isc::asiolink::IOAddress& addr,
+                              Pool::PoolType type) {
+    switch (type) {
+    case Pool::TYPE_V4:
+    case Pool::TYPE_IA:
+        last_allocated_ia_ = addr;
+        return;
+    case Pool::TYPE_TA:
+        last_allocated_ta_ = addr;
+        return;
+    case Pool::TYPE_PD:
+        last_allocated_pd_ = addr;
+        return;
+    default:
+        isc_throw(BadValue, "Pool type " << type << " not supported");
+    }
+}
+
 std::string 
 Subnet::toText() const {
     std::stringstream tmp;
@@ -104,6 +138,10 @@ Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
     }
 }
 
+const PoolCollection& Subnet::getPools() const {
+    return pools_;
+}
+
 void 
 Subnet::addPool(const PoolPtr& pool) {
     IOAddress first_addr = pool->getFirstAddress();

+ 21 - 13
src/lib/dhcpsrv/subnet.h

@@ -240,10 +240,9 @@ public:
     /// @todo: Define map<SubnetID, IOAddress> somewhere in the
     ///        AllocEngine::IterativeAllocator and keep the data there
     ///
-    /// @return address that was last tried from this pool
-    isc::asiolink::IOAddress getLastAllocated() const {
-        return (last_allocated_);
-    }
+    /// @param type lease type to be returned
+    /// @return address/prefix that was last tried from this pool
+    isc::asiolink::IOAddress getLastAllocated(Pool::PoolType type) const;
 
     /// @brief sets the last address that was tried from this pool
     ///
@@ -253,9 +252,10 @@ public:
     ///
     /// @todo: Define map<SubnetID, IOAddress> somewhere in the
     ///        AllocEngine::IterativeAllocator and keep the data there
-    void setLastAllocated(const isc::asiolink::IOAddress& addr) {
-        last_allocated_ = addr;
-    }
+    /// @param addr address/prefix to that was tried last
+    /// @param type lease type to be set
+    void setLastAllocated(const isc::asiolink::IOAddress& addr,
+                          Pool::PoolType type);
 
     /// @brief returns unique ID for that subnet
     /// @return unique ID for that subnet
@@ -280,7 +280,7 @@ public:
 
     /// @brief Returns a pool without any address specified
     /// @return returns one of the pools defined
-    PoolPtr getPool() {
+    PoolPtr getAnyPool() {
         return (getPool(default_pool()));
     }
 
@@ -295,9 +295,7 @@ public:
     /// The reference is only valid as long as the object that returned it.
     ///
     /// @return a collection of all pools
-    const PoolCollection& getPools() const {
-        return pools_;
-    }
+    const PoolCollection& getPools() const;
 
     /// @brief sets name of the network interface for directly attached networks
     ///
@@ -377,7 +375,17 @@ protected:
     /// removing a pool, restarting or changing allocation algorithms. For
     /// that purpose it should be only considered a help that should not be
     /// fully trusted.
-    isc::asiolink::IOAddress last_allocated_;
+    isc::asiolink::IOAddress last_allocated_ia_;
+
+    /// @brief last allocated temporary address
+    ///
+    /// See @ref last_allocated_ia_ for details.
+    isc::asiolink::IOAddress last_allocated_ta_;
+
+    /// @brief last allocated IPv6 prefix
+    ///
+    /// See @ref last_allocated_ia_ for details.
+    isc::asiolink::IOAddress last_allocated_pd_;
 
     /// @brief Name of the network interface (if connected directly)
     std::string iface_;
@@ -493,7 +501,7 @@ protected:
     /// @brief specifies optional interface-id
     OptionPtr interface_id_;
 
-    /// @brief collection of pools in that list
+    /// @brief collection of pools for non-temporary addresses
     Pool6Collection pools_;
 
     /// @brief a triplet with preferred lifetime (in seconds)

+ 4 - 4
src/lib/dhcpsrv/tests/alloc_engine_unittest.cc

@@ -375,7 +375,7 @@ TEST_F(AllocEngine6Test, allocateAddress6Nulls) {
 // pool
 TEST_F(AllocEngine6Test, IterativeAllocator) {
     boost::scoped_ptr<NakedAllocEngine::Allocator>
-        alloc(new NakedAllocEngine::IterativeAllocator());
+        alloc(new NakedAllocEngine::IterativeAllocator(Pool6::TYPE_IA));
 
     for (int i = 0; i < 1000; ++i) {
         IOAddress candidate = alloc->pickAddress(subnet_, duid_, IOAddress("::"));
@@ -388,7 +388,7 @@ TEST_F(AllocEngine6Test, IterativeAllocator) {
 // in all pools in specified subnet. It also must not pick the same address twice
 // unless it runs out of pool space and must start over.
 TEST_F(AllocEngine6Test, IterativeAllocator_manyPools6) {
-    NakedAllocEngine::IterativeAllocator alloc;
+    NakedAllocEngine::IterativeAllocator alloc(Pool6::TYPE_IA);
 
     // let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
     for (int i = 2; i < 10; ++i) {
@@ -829,7 +829,7 @@ TEST_F(AllocEngine4Test, allocateAddress4Nulls) {
 // pool
 TEST_F(AllocEngine4Test, IterativeAllocator) {
     boost::scoped_ptr<NakedAllocEngine::Allocator>
-        alloc(new NakedAllocEngine::IterativeAllocator());
+        alloc(new NakedAllocEngine::IterativeAllocator(Pool6::TYPE_V4));
 
     for (int i = 0; i < 1000; ++i) {
         IOAddress candidate = alloc->pickAddress(subnet_, clientid_,
@@ -843,7 +843,7 @@ TEST_F(AllocEngine4Test, IterativeAllocator) {
 // in all pools in specified subnet. It also must not pick the same address twice
 // unless it runs out of pool space and must start over.
 TEST_F(AllocEngine4Test, IterativeAllocator_manyPools4) {
-    NakedAllocEngine::IterativeAllocator alloc;
+    NakedAllocEngine::IterativeAllocator alloc(Pool6::TYPE_V4);
 
     // Let's start from 2, as there is 2001:db8:1::10 - 2001:db8:1::20 pool already.
     for (int i = 2; i < 10; ++i) {

+ 4 - 4
src/lib/dhcpsrv/tests/subnet_unittest.cc

@@ -69,7 +69,7 @@ TEST(Subnet4Test, Pool4InSubnet4) {
     subnet->addPool(pool1);
 
     // If there's only one pool, get that pool
-    PoolPtr mypool = subnet->getPool();
+    PoolPtr mypool = subnet->getAnyPool();
     EXPECT_EQ(mypool, pool1);
 
 
@@ -78,7 +78,7 @@ TEST(Subnet4Test, Pool4InSubnet4) {
 
     // If there are more than one pool and we didn't provide hint, we
     // should get the first pool
-    mypool = subnet->getPool();
+    mypool = subnet->getAnyPool();
 
     EXPECT_EQ(mypool, pool1);
 
@@ -215,7 +215,7 @@ TEST(Subnet6Test, Pool6InSubnet6) {
     subnet->addPool(pool1);
 
     // If there's only one pool, get that pool
-    PoolPtr mypool = subnet->getPool();
+    PoolPtr mypool = subnet->getAnyPool();
     EXPECT_EQ(mypool, pool1);
 
 
@@ -224,7 +224,7 @@ TEST(Subnet6Test, Pool6InSubnet6) {
 
     // If there are more than one pool and we didn't provide hint, we
     // should get the first pool
-    mypool = subnet->getPool();
+    mypool = subnet->getAnyPool();
 
     EXPECT_EQ(mypool, pool1);