Parcourir la source

[3281] DHCPv6 configuration parser sets the subnet id specified by user.

Marcin Siodelski il y a 11 ans
Parent
commit
f4ba810511

+ 9 - 3
src/bin/dhcp6/config_parser.cc

@@ -1,4 +1,4 @@
-// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
+// Copyright (C) 2012-2014 Internet Systems Consortium, Inc. ("ISC")
 //
 // Permission to use, copy, modify, and/or distribute this software for any
 // purpose with or without fee is hereby granted, provided that the above
@@ -406,7 +406,8 @@ protected:
         if ((config_id.compare("preferred-lifetime") == 0)  ||
             (config_id.compare("valid-lifetime") == 0)  ||
             (config_id.compare("renew-timer") == 0)  ||
-            (config_id.compare("rebind-timer") == 0))  {
+            (config_id.compare("rebind-timer") == 0) ||
+            (config_id.compare("id") == 0)) {
             parser = new Uint32Parser(config_id, uint32_values_);
         } else if ((config_id.compare("subnet") == 0) ||
                    (config_id.compare("interface") == 0) ||
@@ -480,6 +481,10 @@ protected:
         Triplet<uint32_t> t2 = getParam("rebind-timer");
         Triplet<uint32_t> pref = getParam("preferred-lifetime");
         Triplet<uint32_t> valid = getParam("valid-lifetime");
+        // Subnet ID is optional. If it is not supplied the value of 0 is used,
+        // which means autogenerate.
+        SubnetID subnet_id =
+            static_cast<SubnetID>(uint32_values_->getOptionalParam("id", 0));
 
         // Get interface-id option content. For now we support string
         // represenation only
@@ -518,7 +523,8 @@ protected:
         LOG_INFO(dhcp6_logger, DHCP6_CONFIG_NEW_SUBNET).arg(tmp.str());
 
         // Create a new subnet.
-        Subnet6* subnet6 = new Subnet6(addr, len, t1, t2, pref, valid);
+        Subnet6* subnet6 = new Subnet6(addr, len, t1, t2, pref, valid,
+                                       subnet_id);
 
         // Configure interface-id for remote interfaces, if defined
         if (!ifaceid.empty()) {

+ 6 - 0
src/bin/dhcp6/dhcp6.spec

@@ -207,6 +207,12 @@
                   "item_default": ""
                 },
 
+                { "item_name": "id",
+                  "item_type": "integer",
+                  "item_optional": false,
+                  "item_default": 0
+                },
+
                 { "item_name": "interface",
                   "item_type": "string",
                   "item_optional": false,

+ 119 - 16
src/bin/dhcp6/tests/config_parser_unittest.cc

@@ -569,11 +569,10 @@ TEST_F(Dhcp6ParserTest, subnetGlobalDefaults) {
     EXPECT_EQ(1, subnet->getID());
 }
 
-// Goal of this test is to verify that multiple subnets get unique
-// subnet-ids. Also, test checks that it's possible to do reconfiguration
-// multiple times.
 TEST_F(Dhcp6ParserTest, multipleSubnets) {
     ConstElementPtr x;
+    // Collection of four subnets for which ids should be autogenerated
+    // - ids are unspecified or set to 0.
     string config = "{ \"interfaces\": [ \"*\" ],"
         "\"preferred-lifetime\": 3000,"
         "\"rebind-timer\": 2000, "
@@ -584,7 +583,8 @@ TEST_F(Dhcp6ParserTest, multipleSubnets) {
         " },"
         " {"
         "    \"pool\": [ \"2001:db8:2::/80\" ],"
-        "    \"subnet\": \"2001:db8:2::/64\" "
+        "    \"subnet\": \"2001:db8:2::/64\", "
+        "    \"id\": 0"
         " },"
         " {"
         "    \"pool\": [ \"2001:db8:3::/80\" ],"
@@ -623,6 +623,101 @@ TEST_F(Dhcp6ParserTest, multipleSubnets) {
     } while (++cnt < 10);
 }
 
+// This checks that it is possible to assign arbitrary ids for subnets.
+TEST_F(Dhcp6ParserTest, multipleSubnetsExplicitIDs) {
+    ConstElementPtr x;
+    // Collection of four subnets for which ids should be autogenerated
+    // - ids are unspecified or set to 0.
+    string config = "{ \"interfaces\": [ \"*\" ],"
+        "\"preferred-lifetime\": 3000,"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet6\": [ { "
+        "    \"pool\": [ \"2001:db8:1::/80\" ],"
+        "    \"subnet\": \"2001:db8:1::/64\", "
+        "    \"id\": 1024"
+        " },"
+        " {"
+        "    \"pool\": [ \"2001:db8:2::/80\" ],"
+        "    \"subnet\": \"2001:db8:2::/64\", "
+        "    \"id\": 100"
+        " },"
+        " {"
+        "    \"pool\": [ \"2001:db8:3::/80\" ],"
+        "    \"subnet\": \"2001:db8:3::/64\", "
+        "    \"id\": 1"
+        " },"
+        " {"
+        "    \"pool\": [ \"2001:db8:4::/80\" ],"
+        "    \"subnet\": \"2001:db8:4::/64\", "
+        "    \"id\": 34"
+        " } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    int cnt = 0; // Number of reconfigurations
+
+    do {
+        ElementPtr json = Element::fromJSON(config);
+
+        EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
+        ASSERT_TRUE(x);
+        comment_ = parseAnswer(rcode_, x);
+        ASSERT_EQ(0, rcode_);
+
+        const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6();
+        ASSERT_TRUE(subnets);
+        ASSERT_EQ(4, subnets->size()); // We expect 4 subnets
+
+        // Check that subnet ids are as expected.
+        EXPECT_EQ(1024, subnets->at(0)->getID());
+        EXPECT_EQ(100, subnets->at(1)->getID());
+        EXPECT_EQ(1, subnets->at(2)->getID());
+        EXPECT_EQ(34, subnets->at(3)->getID());
+
+        // Repeat reconfiguration process 10 times and check that the subnet-id
+        // is set to the same value.
+    } while (++cnt < 10);
+}
+
+// CHeck that the configuration with two subnets having the same id is rejected.
+TEST_F(Dhcp6ParserTest, multipleSubnetsOverlapingIDs) {
+    ConstElementPtr x;
+    // Four subnets, two of them have the same id.
+    string config = "{ \"interfaces\": [ \"*\" ],"
+        "\"preferred-lifetime\": 3000,"
+        "\"rebind-timer\": 2000, "
+        "\"renew-timer\": 1000, "
+        "\"subnet6\": [ { "
+        "    \"pool\": [ \"2001:db8:1::/80\" ],"
+        "    \"subnet\": \"2001:db8:1::/64\", "
+        "    \"id\": 1024"
+        " },"
+        " {"
+        "    \"pool\": [ \"2001:db8:2::/80\" ],"
+        "    \"subnet\": \"2001:db8:2::/64\", "
+        "    \"id\": 100"
+        " },"
+        " {"
+        "    \"pool\": [ \"2001:db8:3::/80\" ],"
+        "    \"subnet\": \"2001:db8:3::/64\", "
+        "    \"id\": 1024"
+        " },"
+        " {"
+        "    \"pool\": [ \"2001:db8:4::/80\" ],"
+        "    \"subnet\": \"2001:db8:4::/64\", "
+        "    \"id\": 34"
+        " } ],"
+        "\"valid-lifetime\": 4000 }";
+
+    ElementPtr json = Element::fromJSON(config);
+
+    EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
+    ASSERT_TRUE(x);
+    comment_ = parseAnswer(rcode_, x);
+    ASSERT_NE(rcode_, 0);
+}
+
+
 // Goal of this test is to verify that a previously configured subnet can be
 // deleted in subsequent reconfiguration.
 TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
@@ -635,19 +730,23 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
         "\"renew-timer\": 1000, "
         "\"subnet6\": [ { "
         "    \"pool\": [ \"2001:db8:1::/80\" ],"
-        "    \"subnet\": \"2001:db8:1::/64\" "
+        "    \"subnet\": \"2001:db8:1::/64\", "
+        "    \"id\": 1"
         " },"
         " {"
         "    \"pool\": [ \"2001:db8:2::/80\" ],"
-        "    \"subnet\": \"2001:db8:2::/64\" "
+        "    \"subnet\": \"2001:db8:2::/64\", "
+        "    \"id\": 2"
         " },"
         " {"
         "    \"pool\": [ \"2001:db8:3::/80\" ],"
-        "    \"subnet\": \"2001:db8:3::/64\" "
+        "    \"subnet\": \"2001:db8:3::/64\", "
+        "    \"id\": 3"
         " },"
         " {"
         "    \"pool\": [ \"2001:db8:4::/80\" ],"
-        "    \"subnet\": \"2001:db8:4::/64\" "
+        "    \"subnet\": \"2001:db8:4::/64\", "
+        "    \"id\": 4"
         " } ],"
         "\"valid-lifetime\": 4000 }";
 
@@ -658,15 +757,18 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
         "\"renew-timer\": 1000, "
         "\"subnet6\": [ { "
         "    \"pool\": [ \"2001:db8:1::/80\" ],"
-        "    \"subnet\": \"2001:db8:1::/64\" "
+        "    \"subnet\": \"2001:db8:1::/64\", "
+        "    \"id\": 1"
         " },"
         " {"
         "    \"pool\": [ \"2001:db8:2::/80\" ],"
-        "    \"subnet\": \"2001:db8:2::/64\" "
+        "    \"subnet\": \"2001:db8:2::/64\", "
+        "    \"id\": 2"
         " },"
         " {"
         "    \"pool\": [ \"2001:db8:3::/80\" ],"
-        "    \"subnet\": \"2001:db8:3::/64\" "
+        "    \"subnet\": \"2001:db8:3::/64\", "
+        "    \"id\": 3"
         " } ],"
         "\"valid-lifetime\": 4000 }";
 
@@ -677,15 +779,18 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
         "\"renew-timer\": 1000, "
         "\"subnet6\": [ { "
         "    \"pool\": [ \"2001:db8:1::/80\" ],"
-        "    \"subnet\": \"2001:db8:1::/64\" "
+        "    \"subnet\": \"2001:db8:1::/64\", "
+        "    \"id\": 1"
         " },"
         " {"
         "    \"pool\": [ \"2001:db8:3::/80\" ],"
-        "    \"subnet\": \"2001:db8:3::/64\" "
+        "    \"subnet\": \"2001:db8:3::/64\", "
+        "    \"id\": 3"
         " },"
         " {"
         "    \"pool\": [ \"2001:db8:4::/80\" ],"
-        "    \"subnet\": \"2001:db8:4::/64\" "
+        "    \"subnet\": \"2001:db8:4::/64\", "
+        "    \"id\": 4"
         " } ],"
         "\"valid-lifetime\": 4000 }";
 
@@ -720,7 +825,6 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
     /// CASE 2: Configure 4 subnets, then reconfigure and remove one
     /// from in between (not first, not last)
 
-#if 0
     /// @todo: Uncomment subnet removal test as part of #3281.
     json = Element::fromJSON(config4);
     EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json));
@@ -743,7 +847,6 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) {
     // The second subnet (with subnet-id = 2) is no longer there
     EXPECT_EQ(3, subnets->at(1)->getID());
     EXPECT_EQ(4, subnets->at(2)->getID());
-#endif
 }