Browse Source

[3711] Subnet::getLeasesCount() implemented.

Tomek Mrugalski 10 years ago
parent
commit
0aa706ea15

+ 34 - 0
src/lib/dhcpsrv/subnet.cc

@@ -133,6 +133,40 @@ Subnet::toText() const {
     return (tmp.str());
 }
 
+uint64_t
+Subnet::getLeasesCount(Lease::Type type) const {
+    switch (type) {
+    case Lease::TYPE_V4:
+    case Lease::TYPE_NA:
+        return sumLeasesCount(pools_);
+    case Lease::TYPE_TA:
+        return sumLeasesCount(pools_ta_);
+    case Lease::TYPE_PD:
+        return sumLeasesCount(pools_pd_);
+    default:
+        isc_throw(BadValue, "Unsupported pool type: "
+                  << static_cast<int>(type));
+    }
+}
+
+uint64_t
+Subnet::sumLeasesCount(const PoolCollection& pools) const {
+    uint64_t sum = 0;
+    for (PoolCollection::const_iterator p = pools.begin(); p != pools.end(); ++p) {
+        uint64_t x = (*p)->getLeasesCount();
+
+        // Check if we can add it. If sum + x > uint64::max, then we would have
+        // overflown if we tried to add it.
+        if (x > std::numeric_limits<uint64_t>::max() - sum) {
+            return (std::numeric_limits<uint64_t>::max());
+        }
+
+        sum += x;
+    }
+
+    return (sum);
+}
+
 void Subnet4::checkType(Lease::Type type) const {
     if (type != Lease::TYPE_V4) {
         isc_throw(BadValue, "Only TYPE_V4 is allowed for Subnet4");

+ 11 - 0
src/lib/dhcpsrv/subnet.h

@@ -233,6 +233,11 @@ public:
     /// @return a collection of all pools
     const PoolCollection& getPools(Lease::Type type) const;
 
+    /// @brief Returns the number of possible leases for specified lease type
+    ///
+    /// @param type type of the lease
+    uint64_t getLeasesCount(Lease::Type type) const;
+
     /// @brief Sets name of the network interface for directly attached networks
     ///
     /// @param iface_name name of the interface
@@ -403,6 +408,12 @@ protected:
     /// @throw BadValue if invalid value is used
     virtual void checkType(Lease::Type type) const = 0;
 
+
+    /// @brief returns a sum of possible leases in all pools
+    /// @param pools list of pools
+    /// @return sum of possible leases
+    uint64_t sumLeasesCount(const PoolCollection& pools) const;
+
     /// @brief subnet-id
     ///
     /// Subnet-id is a unique value that can be used to find or identify

+ 0 - 1
src/lib/dhcpsrv/tests/pool_unittest.cc

@@ -289,5 +289,4 @@ TEST(Pool6Test, leasesCount) {
 }
 
 
-
 }; // end of anonymous namespace

+ 105 - 0
src/lib/dhcpsrv/tests/subnet_unittest.cc

@@ -22,6 +22,7 @@
 
 #include <boost/scoped_ptr.hpp>
 #include <gtest/gtest.h>
+#include <limits>
 
 // don't import the entire boost namespace.  It will unexpectedly hide uint8_t
 // for some systems.
@@ -147,6 +148,32 @@ TEST(Subnet4Test, Pool4InSubnet4) {
 
 }
 
+// Check if it's possible to get specified number of possible leases for
+// an IPv4 subnet.
+TEST(Subnet4Test, getLeasesCount) {
+
+    // There's one /24 pool.
+    Subnet4Ptr subnet(new Subnet4(IOAddress("192.1.2.0"), 24, 1, 2, 3));
+
+    // There are no pools defined, so the total number of available addrs is 0.
+    EXPECT_EQ(0, subnet->getLeasesCount(Lease::TYPE_V4));
+
+    // Let's add a /25 pool. That's 128 addresses.
+    PoolPtr pool1(new Pool4(IOAddress("192.1.2.0"), 25));
+    subnet->addPool(pool1);
+    EXPECT_EQ(128, subnet->getLeasesCount(Lease::TYPE_V4));
+
+    // Let's add another /26 pool. That's extra 64 addresses.
+    PoolPtr pool2(new Pool4(IOAddress("192.1.2.128"), 26));
+    subnet->addPool(pool2);
+    EXPECT_EQ(192, subnet->getLeasesCount(Lease::TYPE_V4));
+
+    // Let's add a third pool /30. This one has 4 addresses.
+    PoolPtr pool3(new Pool4(IOAddress("192.1.2.192"), 30));
+    subnet->addPool(pool3);
+    EXPECT_EQ(196, subnet->getLeasesCount(Lease::TYPE_V4));
+}
+
 TEST(Subnet4Test, Subnet4_Pool4_checks) {
 
     Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 8, 1, 2, 3));
@@ -434,6 +461,84 @@ TEST(Subnet6Test, relay) {
     EXPECT_EQ("2001:ffff::1", subnet.getRelayInfo().addr_.toText());
 }
 
+// Test checks whether the number of addresses available in the pools are
+// calculated properly.
+TEST(Subnet6Test, Pool6LeasesCount) {
+
+    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));
+
+    // There's 2^16 = 65536 addresses in this one.
+    PoolPtr pool1(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 112));
+
+    // There's 2^32 = 4294967296 addresses in each of those.
+    PoolPtr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:2::"), 96));
+    PoolPtr pool3(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:3::"), 96));
+
+    EXPECT_EQ(0, subnet->getLeasesCount(Lease::TYPE_NA));
+    EXPECT_EQ(0, subnet->getLeasesCount(Lease::TYPE_TA));
+    EXPECT_EQ(0, subnet->getLeasesCount(Lease::TYPE_PD));
+
+    subnet->addPool(pool1);
+    EXPECT_EQ(65536, subnet->getLeasesCount(Lease::TYPE_NA));
+
+    subnet->addPool(pool2);
+    EXPECT_EQ(uint64_t(4294967296 + 65536), subnet->getLeasesCount(Lease::TYPE_NA));
+
+    subnet->addPool(pool3);
+    EXPECT_EQ(uint64_t(4294967296 + 4294967296 + 65536),
+              subnet->getLeasesCount(Lease::TYPE_NA));
+
+    // This is 2^64 prefixes. We're overflown uint64_t.
+    PoolPtr pool4(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:4::"), 64));
+    subnet->addPool(pool4);
+    EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
+              subnet->getLeasesCount(Lease::TYPE_NA));
+
+    PoolPtr pool5(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:5::"), 64));
+    subnet->addPool(pool5);
+    EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
+              subnet->getLeasesCount(Lease::TYPE_NA));
+}
+
+// Test checks whether the number of prefixes available in the pools are
+// calculated properly.
+TEST(Subnet6Test, Pool6PdLeasesCount) {
+
+    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8::"), 32, 1, 2, 3, 4));
+
+    // There's 2^16 = 65536 addresses in this one.
+    PoolPtr pool1(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:1::"), 48, 64));
+
+    // There's 2^32 = 4294967296 addresses in each of those.
+    PoolPtr pool2(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:2::"), 48, 80));
+    PoolPtr pool3(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:3::"), 48, 80));
+
+    EXPECT_EQ(0, subnet->getLeasesCount(Lease::TYPE_NA));
+    EXPECT_EQ(0, subnet->getLeasesCount(Lease::TYPE_TA));
+    EXPECT_EQ(0, subnet->getLeasesCount(Lease::TYPE_PD));
+
+    subnet->addPool(pool1);
+    EXPECT_EQ(65536, subnet->getLeasesCount(Lease::TYPE_PD));
+
+    subnet->addPool(pool2);
+    EXPECT_EQ(uint64_t(4294967296 + 65536), subnet->getLeasesCount(Lease::TYPE_PD));
+
+    subnet->addPool(pool3);
+    EXPECT_EQ(uint64_t(4294967296 + 4294967296 + 65536),
+              subnet->getLeasesCount(Lease::TYPE_PD));
+
+    // This is 2^64.
+    PoolPtr pool4(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:4::"), 48, 112));
+    subnet->addPool(pool4);
+    EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
+              subnet->getLeasesCount(Lease::TYPE_PD));
+
+    PoolPtr pool5(new Pool6(Lease::TYPE_PD, IOAddress("2001:db8:5::"), 48, 112));
+    subnet->addPool(pool5);
+    EXPECT_EQ(std::numeric_limits<uint64_t>::max(),
+              subnet->getLeasesCount(Lease::TYPE_PD));
+}
+
 TEST(Subnet6Test, Pool6InSubnet6) {
 
     Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));