Parcourir la source

[3150] PD support added to Pool6

Tomek Mrugalski il y a 11 ans
Parent
commit
48b5e32efb
3 fichiers modifiés avec 81 ajouts et 9 suppressions
  1. 18 6
      src/lib/dhcpsrv/pool.cc
  2. 32 3
      src/lib/dhcpsrv/pool.h
  3. 31 0
      src/lib/dhcpsrv/tests/pool_unittest.cc

+ 18 - 6
src/lib/dhcpsrv/pool.cc

@@ -32,7 +32,7 @@ bool Pool::inRange(const isc::asiolink::IOAddress& addr) const {
 
 Pool4::Pool4(const isc::asiolink::IOAddress& first,
              const isc::asiolink::IOAddress& last)
-    :Pool(first, last) {
+:Pool(first, last) {
     // check if specified address boundaries are sane
     if (!first.isV4() || !last.isV4()) {
         isc_throw(BadValue, "Invalid Pool4 address boundaries: not IPv4");
@@ -88,23 +88,35 @@ Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& first,
     // parameters are for IA and TA only. There is another dedicated
     // constructor for that (it uses prefix/length)
     if ((type != TYPE_IA) && (type != TYPE_TA)) {
-        isc_throw(BadValue, "Invalid Pool6 type specified");
+        isc_throw(BadValue, "Invalid Pool6 type specified:"
+                  << static_cast<int>(type));
     }
 }
 
 Pool6::Pool6(Pool6Type type, const isc::asiolink::IOAddress& prefix,
-             uint8_t prefix_len)
+             uint8_t prefix_len, uint8_t delegated_len /* = 128 */)
     :Pool(prefix, IOAddress("::")),
-     type_(type) {
+     type_(type), prefix_len_(delegated_len) {
 
     // check if the prefix is sane
     if (!prefix.isV6()) {
         isc_throw(BadValue, "Invalid Pool6 address boundaries: not IPv6");
     }
 
-    // check if the prefix length is sane 
+    // check if the prefix length is sane
     if (prefix_len == 0 || prefix_len > 128) {
-        isc_throw(BadValue, "Invalid prefix length");
+        isc_throw(BadValue, "Invalid prefix length: " << prefix_len);
+    }
+
+    if (prefix_len > delegated_len) {
+        isc_throw(BadValue, "Delegated length (" << static_cast<int>(delegated_len)
+                  << ") must be smaller than prefix length ("
+                  << static_cast<int>(prefix_len) << ")");
+    }
+
+    if ( ( (type == TYPE_IA) || (type == TYPE_TA)) && (delegated_len != 128)) {
+        isc_throw(BadValue, "For IA or TA pools, delegated prefix length must "
+                  << " be 128.");
     }
 
     /// @todo: We should probably implement checks against weird addresses

+ 32 - 3
src/lib/dhcpsrv/pool.h

@@ -143,7 +143,9 @@ public:
 
     /// @brief the constructor for Pool6 "min-max" style definition
     ///
-    /// @param type type of the pool (IA, TA or PD)
+    /// @throw BadValue if PD is define (PD can be only prefix/len)
+    ///
+    /// @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,
@@ -151,11 +153,27 @@ public:
 
     /// @brief the constructor for Pool6 "prefix/len" style definition
     ///
+    /// For addressed, this is just a prefix/len definition. For prefixes,
+    /// there is one extra additional parameter delegated_len. It specifies
+    /// a size of delegated prefixes that the pool will be split into. For
+    /// example pool 2001:db8::/56, delegated_len=64 means that there is a
+    /// pool 2001:db8::/56. It will be split into 256 prefixes of length /64,
+    /// e.g. 2001:db8:0:1::/64, 2001:db8:0:2::/64 etc.
+    ///
+    /// Obviously, prefix_len must define bigger prefix than delegated_len,
+    /// so prefix_len < delegated_len. Note that it is slightly confusing:
+    /// bigger (larger) prefix actually has smaller prefix length, e.g.
+    /// /56 is a bigger prefix than /64.
+    ///
+    /// @throw BadValue if delegated_len is defined for non-PD types or
+    ///        when delegated_len < prefix_len
+    ///
     /// @param type type of the pool (IA, TA or PD)
     /// @param prefix specifies prefix of the pool
-    /// @param prefix_len specifies length of the 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,
-          uint8_t prefix_len);
+          uint8_t prefix_len, uint8_t delegated_len = 128);
 
     /// @brief returns pool type
     ///
@@ -164,10 +182,21 @@ public:
         return (type_);
     }
 
+    /// @brief returns delegated prefix length
+    ///
+    /// This may be useful for "prefix/len" style definition for
+    /// addresses, but is mostly useful for prefix pools.
+    /// @return prefix length (1-128)
+    uint8_t getLength() {
+        return (prefix_len_);
+    }
+
 private:
     /// @brief defines a pool type
     Pool6Type type_;
 
+    /// @brief Defines prefix length (for TYPE_PD only)
+    uint8_t prefix_len_;
 };
 
 /// @brief a pointer an IPv6 Pool

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

@@ -146,6 +146,10 @@ TEST(Pool6Test, constructor_prefix_len) {
     // This is Pool6, IPv4 addresses do not belong here
     EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("192.168.0.2"), 96),
                  BadValue);
+
+    // Delegated prefix length for addresses must be /128
+    EXPECT_THROW(Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1::"), 96, 125),
+                 BadValue);
 }
 
 TEST(Pool6Test, in_range) {
@@ -160,6 +164,33 @@ TEST(Pool6Test, in_range) {
    EXPECT_FALSE(pool1.inRange(IOAddress("::")));
 }
 
+// Checks that Prefix Delegation pools are handled properly
+TEST(Pool6Test, PD) {
+
+    // Let's construct 2001:db8:1::/96 PD pool, split into /112 prefixes
+    Pool6 pool1(Pool6::TYPE_PD, IOAddress("2001:db8:1::"), 96, 112);
+
+    EXPECT_EQ(Pool6::TYPE_PD, pool1.getType());
+    EXPECT_EQ(112, pool1.getLength());
+    EXPECT_EQ("2001:db8:1::", pool1.getFirstAddress().toText());
+    EXPECT_EQ("2001:db8:1::ffff:ffff", pool1.getLastAddress().toText());
+
+    // Check that it's not possible to have min-max range for PD
+    EXPECT_THROW(Pool6 pool2(Pool6::TYPE_PD, IOAddress("2001:db8:1::1"),
+                             IOAddress("2001:db8:1::f")), BadValue);
+
+    // Check that it's not allowed to delegate bigger prefix than the pool
+    // Let's try to split /64 prefix into /56 chunks (should be impossible)
+    EXPECT_THROW(Pool6 pool3(Pool6::TYPE_PD, IOAddress("2001:db8:1::"),
+                             64, 56), BadValue);
+
+    // It should be possible to have a pool split into just a single chunk
+    // Let's try to split 2001:db8:1::/77 into a single /77 delegated prefix
+    EXPECT_NO_THROW(Pool6 pool4(Pool6::TYPE_PD, IOAddress("2001:db8:1::"),
+                                77, 77));
+}
+
+
 // This test creates 100 pools and verifies that their IDs are unique.
 TEST(Pool6Test, unique_id) {