Browse Source

[3281] Allow assigning arbitrary subnet id.

Marcin Siodelski 11 years ago
parent
commit
9ecdae6cef
3 changed files with 78 additions and 14 deletions
  1. 10 7
      src/lib/dhcpsrv/subnet.cc
  2. 13 4
      src/lib/dhcpsrv/subnet.h
  3. 55 3
      src/lib/dhcpsrv/tests/subnet_unittest.cc

+ 10 - 7
src/lib/dhcpsrv/subnet.cc

@@ -31,8 +31,9 @@ Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
                const Triplet<uint32_t>& t1,
                const Triplet<uint32_t>& t2,
                const Triplet<uint32_t>& valid_lifetime,
-               const isc::dhcp::Subnet::RelayInfo& relay)
-    :id_(generateNextID()), prefix_(prefix), prefix_len_(len),
+               const isc::dhcp::Subnet::RelayInfo& relay,
+               const SubnetID id)
+    :id_(id == 0 ? generateNextID() : id), prefix_(prefix), prefix_len_(len),
      t1_(t1), t2_(t2), valid_(valid_lifetime),
      last_allocated_ia_(lastAddrInPrefix(prefix, len)),
      last_allocated_ta_(lastAddrInPrefix(prefix, len)),
@@ -211,9 +212,10 @@ void Subnet4::checkType(Lease::Type type) const {
 Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
                  const Triplet<uint32_t>& t1,
                  const Triplet<uint32_t>& t2,
-                 const Triplet<uint32_t>& valid_lifetime)
+                 const Triplet<uint32_t>& valid_lifetime,
+                 const SubnetID id)
 :Subnet(prefix, length, t1, t2, valid_lifetime,
-        RelayInfo(IOAddress("0.0.0.0"))), siaddr_(IOAddress("0.0.0.0")) {
+        RelayInfo(IOAddress("0.0.0.0")), id), siaddr_(IOAddress("0.0.0.0")) {
     if (!prefix.isV4()) {
         isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText()
                   << " specified in subnet4");
@@ -363,9 +365,10 @@ Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
                  const Triplet<uint32_t>& t1,
                  const Triplet<uint32_t>& t2,
                  const Triplet<uint32_t>& preferred_lifetime,
-                 const Triplet<uint32_t>& valid_lifetime)
-:Subnet(prefix, length, t1, t2, valid_lifetime, RelayInfo(IOAddress("::"))),
-     preferred_(preferred_lifetime){
+                 const Triplet<uint32_t>& valid_lifetime,
+                 const SubnetID id)
+:Subnet(prefix, length, t1, t2, valid_lifetime, RelayInfo(IOAddress("::")), id),
+     preferred_(preferred_lifetime) {
     if (!prefix.isV6()) {
         isc_throw(BadValue, "Non IPv6 prefix " << prefix
                   << " specified in subnet6");

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

@@ -466,7 +466,7 @@ protected:
 
     /// @brief Protected constructor
     //
-    /// By making the constructor protected, we make sure that noone will
+    /// By making the constructor protected, we make sure that no one will
     /// ever instantiate that class. Subnet4 and Subnet6 should be used instead.
     ///
     /// This constructor assigns a new subnet-id (see @ref generateNextID).
@@ -480,11 +480,14 @@ protected:
     /// @param t2 T2 (rebind-time) timer, expressed in seconds
     /// @param valid_lifetime valid lifetime of leases in this subnet (in seconds)
     /// @param relay optional relay information (currently with address only)
+    /// @param id arbitraty subnet id, value of 0 triggers autogeneration
+    /// of subnet id
     Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
            const Triplet<uint32_t>& t1,
            const Triplet<uint32_t>& t2,
            const Triplet<uint32_t>& valid_lifetime,
-           const isc::dhcp::Subnet::RelayInfo& relay);
+           const isc::dhcp::Subnet::RelayInfo& relay,
+           const SubnetID id);
 
     /// @brief virtual destructor
     ///
@@ -637,10 +640,13 @@ public:
     /// @param t1 renewal timer (in seconds)
     /// @param t2 rebind timer (in seconds)
     /// @param valid_lifetime preferred lifetime of leases (in seconds)
+    /// @param id arbitraty subnet id, default value of 0 triggers
+    /// autogeneration of subnet id
     Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
             const Triplet<uint32_t>& t1,
             const Triplet<uint32_t>& t2,
-            const Triplet<uint32_t>& valid_lifetime);
+            const Triplet<uint32_t>& valid_lifetime,
+            const SubnetID id = 0);
 
     /// @brief Sets siaddr for the Subnet4
     ///
@@ -704,11 +710,14 @@ public:
     /// @param t2 rebind timer (in seconds)
     /// @param preferred_lifetime preferred lifetime of leases (in seconds)
     /// @param valid_lifetime preferred lifetime of leases (in seconds)
+    /// @param id arbitraty subnet id, default value of 0 triggers
+    /// autogeneration of subnet id
     Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
             const Triplet<uint32_t>& t1,
             const Triplet<uint32_t>& t2,
             const Triplet<uint32_t>& preferred_lifetime,
-            const Triplet<uint32_t>& valid_lifetime);
+            const Triplet<uint32_t>& valid_lifetime,
+            const SubnetID id = 0);
 
     /// @brief Returns preverred lifetime (in seconds)
     ///

+ 55 - 3
src/lib/dhcpsrv/tests/subnet_unittest.cc

@@ -34,7 +34,7 @@ namespace {
 
 TEST(Subnet4Test, constructor) {
     EXPECT_NO_THROW(Subnet4 subnet1(IOAddress("192.0.2.2"), 16,
-                                    1, 2, 3));
+                                    1, 2, 3, 10));
 
     EXPECT_THROW(Subnet4 subnet2(IOAddress("192.0.2.0"), 33, 1, 2, 3),
                 BadValue); // invalid prefix length
@@ -42,7 +42,33 @@ TEST(Subnet4Test, constructor) {
                 BadValue); // IPv6 addresses are not allowed in Subnet4
 }
 
-TEST(Subnet4Test, in_range) {
+// Checks that the subnet id can be either autogenerated or set to an
+// arbitrary value through the constructor.
+TEST(Subnet4Test, subnetID) {
+    // Create subnet and don't specify id, so as it is autogenerated.
+    Subnet4Ptr subnet(new Subnet4(IOAddress("192.0.2.0"), 24, 1000, 2000,
+                                  3000));
+    SubnetID id0 = subnet->getID();
+
+    // Create another subnet and let id be autogenerated.
+    subnet.reset(new Subnet4(IOAddress("192.0.3.0"), 24, 1000, 2000,
+                             3000));
+    SubnetID id1 = subnet->getID();
+
+    // The autogenerated ids must not be equal.
+    EXPECT_NE(id0, id1);
+
+    // Create third subnet but this time select an arbitrary id. The id
+    // we use us the one of second subnet. That way we ensure that the
+    // subnet id we provide via constructor is used and it is not
+    // autogenerated - if it was autogenerated we would get id other
+    // than id1 because id1 has already been used.
+    subnet.reset(new Subnet4(IOAddress("192.0.4.0"), 24, 1000, 2000,
+                             3000, id1));
+    EXPECT_EQ(id1, subnet->getID());
+}
+
+TEST(Subnet4Test, inRange) {
     Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000);
 
     EXPECT_EQ(1000, subnet.getT1());
@@ -362,7 +388,33 @@ TEST(Subnet6Test, constructor) {
                 BadValue); // IPv4 addresses are not allowed in Subnet6
 }
 
-TEST(Subnet6Test, in_range) {
+// Checks that the subnet id can be either autogenerated or set to an
+// arbitrary value through the constructor.
+TEST(Subnet6Test, subnetID) {
+    // Create subnet and don't specify id, so as it is autogenerated.
+    Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 64, 1000, 2000,
+                                  3000, 4000));
+    SubnetID id0 = subnet->getID();
+
+    // Create another subnet and let id be autogenerated.
+    subnet.reset(new Subnet6(IOAddress("2001:db8:2::"), 64, 1000, 2000,
+                             3000, 4000));
+    SubnetID id1 = subnet->getID();
+
+    // The autogenerated ids must not be equal.
+    EXPECT_NE(id0, id1);
+
+    // Create third subnet but this time select an arbitrary id. The id
+    // we use us the one of second subnet. That way we ensure that the
+    // subnet id we provide via constructor is used and it is not
+    // autogenerated - if it was autogenerated we would get id other
+    // than id1 because id1 has already been used.
+    subnet.reset(new Subnet6(IOAddress("2001:db8:3::"), 64, 1000, 2000,
+                             3000, 4000, id1));
+    EXPECT_EQ(id1, subnet->getID());
+}
+
+TEST(Subnet6Test, inRange) {
     Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000);
 
     EXPECT_EQ(1000, subnet.getT1());