From 4a5895b993893f73bfd7964636dc1f47d88936c7 Mon Sep 17 00:00:00 2001 From: Marcin Siodelski Date: Thu, 30 Oct 2014 12:44:37 +0100 Subject: [PATCH] [3625] Use CfgSubnets6 to obtain subnet information. --- src/bin/dhcp6/dhcp6_srv.cc | 55 ++- src/bin/dhcp6/json_config_parser.cc | 8 +- src/bin/dhcp6/tests/config_parser_unittest.cc | 132 ++++--- src/bin/dhcp6/tests/confirm_unittest.cc | 5 +- .../dhcp6/tests/ctrl_dhcp6_srv_unittest.cc | 7 +- src/bin/dhcp6/tests/d2_unittest.cc | 1 + src/bin/dhcp6/tests/dhcp6_message_test.cc | 7 +- src/bin/dhcp6/tests/dhcp6_srv_unittest.cc | 113 +++--- src/bin/dhcp6/tests/dhcp6_test_utils.cc | 7 +- src/bin/dhcp6/tests/dhcp6_test_utils.h | 2 +- src/bin/dhcp6/tests/fqdn_unittest.cc | 5 +- src/bin/dhcp6/tests/hooks_unittest.cc | 10 +- .../dhcp6/tests/kea_controller_unittest.cc | 6 +- src/bin/dhcp6/tests/rebind_unittest.cc | 16 +- src/bin/dhcp6/tests/sarr_unittest.cc | 3 +- src/lib/dhcpsrv/cfg_subnets6.cc | 2 +- src/lib/dhcpsrv/cfgmgr.cc | 108 ------ src/lib/dhcpsrv/cfgmgr.h | 91 ----- src/lib/dhcpsrv/srv_config.cc | 2 +- src/lib/dhcpsrv/subnet_selector.h | 9 +- .../dhcpsrv/tests/alloc_engine_unittest.cc | 15 +- src/lib/dhcpsrv/tests/cfgmgr_unittest.cc | 322 ------------------ .../dhcpsrv/tests/dhcp_parsers_unittest.cc | 1 - src/lib/dhcpsrv/tests/srv_config_unittest.cc | 18 +- 24 files changed, 222 insertions(+), 723 deletions(-) diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index f51cf840a5..8b5336cde5 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -868,43 +869,25 @@ Dhcpv6Srv::sanityCheck(const Pkt6Ptr& pkt, RequirementLevel clientid, Subnet6Ptr Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) { + // Initialize subnet selector with the values used to select the subnet. + SubnetSelector selector; + selector.iface_name_ = question->getIface(); + selector.remote_address_ = question->getRemoteAddr(); + selector.first_relay_linkaddr_ = IOAddress("::"); + selector.client_classes_ = question->classes_; - Subnet6Ptr subnet; - - if (question->relay_info_.empty()) { - // This is a direct (non-relayed) message - - // Try to find a subnet if received packet from a directly connected client - subnet = CfgMgr::instance().getSubnet6(question->getIface(), - question->classes_); - if (!subnet) { - // If no subnet was found, try to find it based on remote address - subnet = CfgMgr::instance().getSubnet6(question->getRemoteAddr(), - question->classes_); - } - } else { - - // This is a relayed message - OptionPtr interface_id = question->getAnyRelayOption(D6O_INTERFACE_ID, - Pkt6::RELAY_GET_FIRST); - if (interface_id) { - subnet = CfgMgr::instance().getSubnet6(interface_id, - question->classes_); - } - - if (!subnet) { - // If no interface-id was specified (or not configured on server), - // let's try address matching - IOAddress link_addr = question->relay_info_.back().linkaddr_; - - // if relay filled in link_addr field, then let's use it - if (link_addr != IOAddress("::")) { - subnet = CfgMgr::instance().getSubnet6(link_addr, - question->classes_, true); - } - } + // Initialize fields specific to relayed messages. + if (!question->relay_info_.empty()) { + selector.first_relay_linkaddr_ = question->relay_info_.back().linkaddr_; + selector.interface_id_ = + question->getAnyRelayOption(D6O_INTERFACE_ID, + Pkt6::RELAY_GET_FIRST); } + Subnet6Ptr subnet = CfgMgr::instance().getCurrentCfg()-> + getCfgSubnets6()->selectSubnet(selector); + + // Let's execute all callouts registered for subnet6_receive if (HooksManager::calloutsPresent(Hooks.hook_index_subnet6_select_)) { CalloutHandlePtr callout_handle = getCalloutHandle(question); @@ -919,7 +902,9 @@ Dhcpv6Srv::selectSubnet(const Pkt6Ptr& question) { // We pass pointer to const collection for performance reasons. // Otherwise we would get a non-trivial performance penalty each // time subnet6_select is called. - callout_handle->setArgument("subnet6collection", CfgMgr::instance().getSubnets6()); + callout_handle->setArgument("subnet6collection", + CfgMgr::instance().getCurrentCfg()-> + getCfgSubnets6()->getAll()); // Call user (and server-side) callouts HooksManager::callCallouts(Hooks.hook_index_subnet6_select_, *callout_handle); diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index 40ca980313..707766a780 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -344,7 +344,7 @@ public: // subnet id is invalid (duplicate). Thus, we catch exceptions // here to append a position in the configuration string. try { - isc::dhcp::CfgMgr::instance().addSubnet6(sub6ptr); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(sub6ptr); } catch (const std::exception& ex) { isc_throw(DhcpConfigError, ex.what() << " (" << subnet->getPosition() << ")"); @@ -534,12 +534,6 @@ public: /// /// @param subnets_list pointer to a list of IPv6 subnets void build(ConstElementPtr subnets_list) { - // @todo: Implement more subtle reconfiguration than toss - // the old one and replace with the new one. - - // remove old subnets - isc::dhcp::CfgMgr::instance().deleteSubnets6(); - BOOST_FOREACH(ConstElementPtr subnet, subnets_list->listValue()) { ParserPtr parser(new Subnet6ConfigParser("subnet")); parser->build(subnet); diff --git a/src/bin/dhcp6/tests/config_parser_unittest.cc b/src/bin/dhcp6/tests/config_parser_unittest.cc index f6f445cf5a..929289ff89 100644 --- a/src/bin/dhcp6/tests/config_parser_unittest.cc +++ b/src/bin/dhcp6/tests/config_parser_unittest.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -247,13 +248,13 @@ public: getOptionFromSubnet(const IOAddress& subnet_address, const uint16_t option_code, const uint16_t expected_options_count = 1) { - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(subnet_address, - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(subnet_address, classify_); if (!subnet) { /// @todo replace toText() with the use of operator <<. ADD_FAILURE() << "A subnet for the specified address " << subnet_address.toText() - << "does not exist in Config Manager"; + << " does not exist in Config Manager"; } OptionContainerPtr options = subnet->getCfgOption()->getAll("dhcp6"); @@ -469,6 +470,8 @@ public: const uint16_t option_code, const uint8_t* expected_data, const size_t expected_data_len) { + CfgMgr::instance().clear(); + std::string config = createConfigWithOption(params); ASSERT_TRUE(executeConfiguration(config, "parse option configuration")); @@ -557,8 +560,8 @@ TEST_F(Dhcp6ParserTest, subnetGlobalDefaults) { // Now check if the configuration was indeed handled and we have // expected pool configured. - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); EXPECT_EQ(1000, subnet->getT1()); EXPECT_EQ(2000, subnet->getT2()); @@ -605,7 +608,10 @@ TEST_F(Dhcp6ParserTest, multipleSubnets) { EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + CfgMgr::instance().commit(); + + const Subnet6Collection* subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_TRUE(subnets); ASSERT_EQ(4, subnets->size()); // We expect 4 subnets @@ -660,7 +666,10 @@ TEST_F(Dhcp6ParserTest, multipleSubnetsExplicitIDs) { EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + CfgMgr::instance().commit(); + + const Subnet6Collection* subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_TRUE(subnets); ASSERT_EQ(4, subnets->size()); // We expect 4 subnets @@ -796,7 +805,10 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) { EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + CfgMgr::instance().commit(); + + const Subnet6Collection* subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_TRUE(subnets); ASSERT_EQ(4, subnets->size()); // We expect 4 subnets @@ -805,7 +817,9 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) { EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); - subnets = CfgMgr::instance().getSubnets6(); + CfgMgr::instance().commit(); + + subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_TRUE(subnets); ASSERT_EQ(3, subnets->size()); // We expect 3 subnets now (4th is removed) @@ -820,12 +834,16 @@ TEST_F(Dhcp6ParserTest, reconfigureRemoveSubnet) { EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); + CfgMgr::instance().commit(); + // Do reconfiguration json = Element::fromJSON(config_second_removed); EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); - subnets = CfgMgr::instance().getSubnets6(); + CfgMgr::instance().commit(); + + subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_TRUE(subnets); ASSERT_EQ(3, subnets->size()); // We expect 4 subnets @@ -863,8 +881,8 @@ TEST_F(Dhcp6ParserTest, subnetLocal) { // returned value should be 0 (configuration success) checkResult(status, 0); - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); EXPECT_EQ(1, subnet->getT1()); EXPECT_EQ(2, subnet->getT2()); @@ -898,8 +916,8 @@ TEST_F(Dhcp6ParserTest, subnetInterface) { // returned value should be 0 (configuration success) checkResult(status, 0); - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); EXPECT_EQ(valid_iface_, subnet->getIface()); } @@ -931,8 +949,8 @@ TEST_F(Dhcp6ParserTest, subnetInterfaceBogus) { checkResult(status, 1); EXPECT_TRUE(errorContainsPosition(status, "")); - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); EXPECT_FALSE(subnet); } @@ -993,16 +1011,20 @@ TEST_F(Dhcp6ParserTest, subnetInterfaceId) { // Try to get a subnet based on bogus interface-id option OptionBuffer tmp(bogus_interface_id.begin(), bogus_interface_id.end()); - OptionPtr ifaceid(new Option(Option::V6, D6O_INTERFACE_ID, tmp)); - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(ifaceid, classify_); + SubnetSelector selector; + selector.first_relay_linkaddr_ = IOAddress("5000::1"); + selector.interface_id_.reset(new Option(Option::V6, D6O_INTERFACE_ID, tmp)); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(selector); EXPECT_FALSE(subnet); // Now try to get subnet for valid interface-id value tmp = OptionBuffer(valid_interface_id.begin(), valid_interface_id.end()); - ifaceid.reset(new Option(Option::V6, D6O_INTERFACE_ID, tmp)); - subnet = CfgMgr::instance().getSubnet6(ifaceid, classify_); + selector.interface_id_.reset(new Option(Option::V6, D6O_INTERFACE_ID, tmp)); + subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(selector); ASSERT_TRUE(subnet); - EXPECT_TRUE(ifaceid->equals(subnet->getInterfaceId())); + EXPECT_TRUE(selector.interface_id_->equals(subnet->getInterfaceId())); } @@ -1084,7 +1106,8 @@ TEST_F(Dhcp6ParserTest, multiplePools) { ASSERT_NO_THROW(status = configureDhcp6Server(srv_, json)); checkResult(status, 0); - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->getAll(); ASSERT_TRUE(subnets); ASSERT_EQ(2, subnets->size()); // We expect 2 subnets @@ -1163,8 +1186,8 @@ TEST_F(Dhcp6ParserTest, poolPrefixLen) { // returned value must be 1 (configuration parse error) checkResult(x, 0); - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); EXPECT_EQ(1000, subnet->getT1()); EXPECT_EQ(2000, subnet->getT2()); @@ -1205,8 +1228,8 @@ TEST_F(Dhcp6ParserTest, pdPoolBasics) { checkResult(x, 0); // Test that we can retrieve the subnet. - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); // Fetch the collection of PD pools. It should have 1 entry. @@ -1277,8 +1300,8 @@ TEST_F(Dhcp6ParserTest, pdPoolList) { checkResult(x, 0); // Test that we can retrieve the subnet. - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); // Fetch the collection of NA pools. It should have 1 entry. @@ -1333,8 +1356,8 @@ TEST_F(Dhcp6ParserTest, subnetAndPrefixDelegated) { checkResult(x, 0); // Test that we can retrieve the subnet. - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); @@ -2027,8 +2050,8 @@ TEST_F(Dhcp6ParserTest, optionDataDefaults) { EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); OptionContainerPtr options = subnet->getCfgOption()->getAll("dhcp6"); ASSERT_EQ(2, options->size()); @@ -2122,8 +2145,8 @@ TEST_F(Dhcp6ParserTest, optionDataTwoSpaces) { checkResult(status, 0); // Options should be now available for the subnet. - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); // Try to get the option from the space dhcp6. OptionDescriptor desc1 = subnet->getCfgOption()->get("dhcp6", 38); @@ -2278,8 +2301,8 @@ TEST_F(Dhcp6ParserTest, optionDataEncapsulate) { checkResult(status, 0); // Get the subnet. - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); // We should have one option available. @@ -2341,8 +2364,8 @@ TEST_F(Dhcp6ParserTest, optionDataInMultipleSubnets) { EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); - Subnet6Ptr subnet1 = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet1 = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet1); OptionContainerPtr options1 = subnet1->getCfgOption()->getAll("dhcp6"); ASSERT_EQ(1, options1->size()); @@ -2367,8 +2390,8 @@ TEST_F(Dhcp6ParserTest, optionDataInMultipleSubnets) { sizeof(subid_expected)); // Test another subnet in the same way. - Subnet6Ptr subnet2 = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:2::4"), - classify_); + Subnet6Ptr subnet2 = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:2::4"), classify_); ASSERT_TRUE(subnet2); OptionContainerPtr options2 = subnet2->getCfgOption()->getAll("dhcp6"); ASSERT_EQ(1, options2->size()); @@ -2402,8 +2425,6 @@ TEST_F(Dhcp6ParserTest, optionDataBoolean) { ASSERT_TRUE(executeConfiguration(config, "parse configuration with a" " boolean value")); - CfgMgr::instance().commit(); - // The subnet should now hold one option with the code 1000. OptionDescriptor desc = getOptionFromSubnet(IOAddress("2001:db8:1::5"), 1000); @@ -2538,8 +2559,8 @@ TEST_F(Dhcp6ParserTest, optionDataLowerCase) { EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); OptionContainerPtr options = subnet->getCfgOption()->getAll("dhcp6"); ASSERT_EQ(1, options->size()); @@ -2581,8 +2602,8 @@ TEST_F(Dhcp6ParserTest, stdOptionData) { EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); OptionContainerPtr options = subnet->getCfgOption()->getAll("dhcp6"); ASSERT_EQ(1, options->size()); @@ -2659,8 +2680,8 @@ TEST_F(Dhcp6ParserTest, vendorOptionsHex) { checkResult(status, 0); // Options should be now available for the subnet. - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); // Try to get the option from the vendor space 4491 @@ -2721,8 +2742,8 @@ TEST_F(Dhcp6ParserTest, vendorOptionsCsv) { checkResult(status, 0); // Options should be now available for the subnet. - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); // Try to get the option from the vendor space 4491 @@ -2864,8 +2885,8 @@ TEST_F(Dhcp6ParserTest, DISABLED_stdOptionDataEncapsulate) { checkResult(status, 0); // Get the subnet. - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::5"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::5"), classify_); ASSERT_TRUE(subnet); // We should have one option available. @@ -3151,8 +3172,8 @@ TEST_F(Dhcp6ParserTest, subnetRelayInfo) { // returned value should be 0 (configuration success) checkResult(status, 0); - Subnet6Ptr subnet = CfgMgr::instance().getSubnet6(IOAddress("2001:db8:1::1"), - classify_); + Subnet6Ptr subnet = CfgMgr::instance().getStagingCfg()->getCfgSubnets6()-> + selectSubnet(IOAddress("2001:db8:1::1"), classify_); ASSERT_TRUE(subnet); EXPECT_EQ("2001:db8:1::abcd", subnet->getRelayInfo().addr_.toText()); } @@ -3191,7 +3212,8 @@ TEST_F(Dhcp6ParserTest, classifySubnets) { EXPECT_NO_THROW(x = configureDhcp6Server(srv_, json)); checkResult(x, 0); - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->getAll(); ASSERT_TRUE(subnets); ASSERT_EQ(4, subnets->size()); // We expect 4 subnets diff --git a/src/bin/dhcp6/tests/confirm_unittest.cc b/src/bin/dhcp6/tests/confirm_unittest.cc index d880e8d26f..d70c9001f9 100644 --- a/src/bin/dhcp6/tests/confirm_unittest.cc +++ b/src/bin/dhcp6/tests/confirm_unittest.cc @@ -233,7 +233,8 @@ TEST_F(ConfirmTest, relayedClientNoAddress) { // Configure the server. configure(CONFIRM_CONFIGS[1], *client.getServer()); // Make sure we ended-up having expected number of subnets configured. - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_EQ(2, subnets->size()); // Client to send relayed message. client.useRelay(); @@ -255,7 +256,7 @@ TEST_F(ConfirmTest, relayedClientNoSubnet) { ASSERT_NO_FATAL_FAILURE(requestLease(CONFIRM_CONFIGS[1], 2, client)); // Now that the client has a lease, let's remove any subnets to check // how the server would respond to the Confirm. - ASSERT_NO_THROW(CfgMgr::instance().deleteSubnets6()); + ASSERT_NO_THROW(CfgMgr::instance().clear()); // Send Confirm message to the server. ASSERT_NO_THROW(client.doConfirm()); // Client should have received a status code option and this option should diff --git a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc index 56c3823d03..cfabee58d4 100644 --- a/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc +++ b/src/bin/dhcp6/tests/ctrl_dhcp6_srv_unittest.cc @@ -182,7 +182,7 @@ TEST_F(CtrlDhcpv6SrvTest, configReload) { ElementPtr config = Element::fromJSON(config_txt); // Make sure there are no subnets configured. - CfgMgr::instance().deleteSubnets6(); + CfgMgr::instance().clear(); // Now send the command int rcode = -1; @@ -192,11 +192,12 @@ TEST_F(CtrlDhcpv6SrvTest, configReload) { EXPECT_EQ(0, rcode); // Expect success // Check that the config was indeed applied. - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->getAll(); EXPECT_EQ(3, subnets->size()); // Clean up after the test. - CfgMgr::instance().deleteSubnets6(); + CfgMgr::instance().clear(); } } // End of anonymous namespace diff --git a/src/bin/dhcp6/tests/d2_unittest.cc b/src/bin/dhcp6/tests/d2_unittest.cc index 9cc9e96d97..34ffd71c36 100644 --- a/src/bin/dhcp6/tests/d2_unittest.cc +++ b/src/bin/dhcp6/tests/d2_unittest.cc @@ -128,6 +128,7 @@ Dhcp6SrvD2Test::configureD2(bool enable_d2, const bool exp_result, void Dhcp6SrvD2Test::configure(const std::string& config, bool exp_result) { + CfgMgr::instance().clear(); ElementPtr json = Element::fromJSON(config); ConstElementPtr status; diff --git a/src/bin/dhcp6/tests/dhcp6_message_test.cc b/src/bin/dhcp6/tests/dhcp6_message_test.cc index 000b65620a..e530e10f88 100644 --- a/src/bin/dhcp6/tests/dhcp6_message_test.cc +++ b/src/bin/dhcp6/tests/dhcp6_message_test.cc @@ -53,7 +53,8 @@ Dhcpv6MessageTest::requestLease(const std::string& config, // Configure the server. configure(config, *client.getServer()); // Make sure we ended-up having expected number of subnets configured. - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_EQ(subnets_num, subnets->size()); // Do the actual 4-way exchange. ASSERT_NO_THROW(client.doSARR()); @@ -63,8 +64,8 @@ Dhcpv6MessageTest::requestLease(const std::string& config, // subnets. ASSERT_EQ(1, client.getLeaseNum()); Lease6 lease_client = client.getLease(0); - ASSERT_TRUE(CfgMgr::instance().getSubnet6(lease_client.addr_, - ClientClasses())); + ASSERT_TRUE(CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()-> + selectSubnet(lease_client.addr_, ClientClasses())); // Check that the client's lease matches the information on the server // side. Lease6Ptr lease_server = checkLease(lease_client); diff --git a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc index dd3e94154e..6bf2c65c76 100644 --- a/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc +++ b/src/bin/dhcp6/tests/dhcp6_srv_unittest.cc @@ -1182,8 +1182,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetAddr) { // CASE 1: We have only one subnet defined and we received local traffic. // The only available subnet used to be picked, but not anymore - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); // just a single subnet + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); // just a single subnet + CfgMgr::instance().commit(); Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); pkt->setRemoteAddr(IOAddress("fe80::abcd")); @@ -1196,38 +1197,42 @@ TEST_F(Dhcpv6SrvTest, selectSubnetAddr) { // We should NOT select it. // Identical steps as in case 1, but repeated for clarity - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); // just a single subnet + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); // just a single subnet + CfgMgr::instance().commit(); pkt->setRemoteAddr(IOAddress("2001:db8:abcd::2345")); Subnet6Ptr selected = srv.selectSubnet(pkt); EXPECT_FALSE(selected); // CASE 3: We have three subnets defined and we received local traffic. // Nothing should be selected. - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); - CfgMgr::instance().addSubnet6(subnet2); - CfgMgr::instance().addSubnet6(subnet3); + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); + CfgMgr::instance().commit(); pkt->setRemoteAddr(IOAddress("fe80::abcd")); selected = srv.selectSubnet(pkt); EXPECT_FALSE(selected); // CASE 4: We have three subnets defined and we received relayed traffic // that came out of subnet 2. We should select subnet2 then - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); - CfgMgr::instance().addSubnet6(subnet2); - CfgMgr::instance().addSubnet6(subnet3); + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); + CfgMgr::instance().commit(); pkt->setRemoteAddr(IOAddress("2001:db8:2::baca")); selected = srv.selectSubnet(pkt); EXPECT_EQ(selected, subnet2); // CASE 5: We have three subnets defined and we received relayed traffic // that came out of undefined subnet. We should select nothing - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); - CfgMgr::instance().addSubnet6(subnet2); - CfgMgr::instance().addSubnet6(subnet3); + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); + CfgMgr::instance().commit(); pkt->setRemoteAddr(IOAddress("2001:db8:4::baca")); EXPECT_FALSE(srv.selectSubnet(pkt)); } @@ -1246,8 +1251,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetIface) { // CASE 1: We have only one subnet defined and it is available via eth0. // Packet came from eth0. The only available subnet should be selected - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); // just a single subnet + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); // just a single subnet + CfgMgr::instance().commit(); Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); pkt->setIface("eth0"); @@ -1257,8 +1263,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetIface) { // CASE 2: We have only one subnet defined and it is available via eth0. // Packet came from eth1. We should not select it - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); // just a single subnet + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); // just a single subnet + CfgMgr::instance().commit(); pkt->setIface("eth1"); @@ -1268,10 +1275,11 @@ TEST_F(Dhcpv6SrvTest, selectSubnetIface) { // CASE 3: We have only 3 subnets defined, one over eth0, one remote and // one over wifi1. // Packet came from eth1. We should not select it - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); - CfgMgr::instance().addSubnet6(subnet2); - CfgMgr::instance().addSubnet6(subnet3); + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); + CfgMgr::instance().commit(); pkt->setIface("eth0"); EXPECT_EQ(subnet1, srv.selectSubnet(pkt)); @@ -1298,8 +1306,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) { // CASE 1: We have only one subnet defined and we received relayed traffic. // The only available subnet should NOT be selected. - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); // just a single subnet + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); // just a single subnet + CfgMgr::instance().commit(); Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); pkt->relay_info_.push_back(relay); @@ -1309,19 +1318,21 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) { // CASE 2: We have three subnets defined and we received relayed traffic. // Nothing should be selected. - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); - CfgMgr::instance().addSubnet6(subnet2); - CfgMgr::instance().addSubnet6(subnet3); + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); + CfgMgr::instance().commit(); selected = srv.selectSubnet(pkt); EXPECT_EQ(selected, subnet2); // CASE 3: We have three subnets defined and we received relayed traffic // that came out of subnet 2. We should select subnet2 then - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); - CfgMgr::instance().addSubnet6(subnet2); - CfgMgr::instance().addSubnet6(subnet3); + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); + CfgMgr::instance().commit(); // Source of the packet should have no meaning. Selection is based // on linkaddr field in the relay @@ -1331,10 +1342,11 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) { // CASE 4: We have three subnets defined and we received relayed traffic // that came out of undefined subnet. We should select nothing - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); - CfgMgr::instance().addSubnet6(subnet2); - CfgMgr::instance().addSubnet6(subnet3); + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); + CfgMgr::instance().commit(); pkt->relay_info_.clear(); relay.linkaddr_ = IOAddress("2001:db8:4::1234"); pkt->relay_info_.push_back(relay); @@ -1357,8 +1369,9 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayInterfaceId) { // CASE 1: We have only one subnet defined and it is for interface-id "relay1" // Packet came with interface-id "relay2". We should not select subnet1 - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); // just a single subnet + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); // just a single subnet + CfgMgr::instance().commit(); Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); Pkt6::RelayInfo relay; @@ -1374,18 +1387,20 @@ TEST_F(Dhcpv6SrvTest, selectSubnetRelayInterfaceId) { // CASE 2: We have only one subnet defined and it is for interface-id "relay2" // Packet came with interface-id "relay2". We should select it - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet2); // just a single subnet + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); // just a single subnet + CfgMgr::instance().commit(); selected = srv.selectSubnet(pkt); EXPECT_EQ(selected, subnet2); // CASE 3: We have only 3 subnets defined: one remote for interface-id "relay1", // one remote for interface-id "relay2" and third local // packet comes with interface-id "relay2". We should select subnet2 - CfgMgr::instance().deleteSubnets6(); - CfgMgr::instance().addSubnet6(subnet1); - CfgMgr::instance().addSubnet6(subnet2); - CfgMgr::instance().addSubnet6(subnet3); + CfgMgr::instance().clear(); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet1); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet2); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet3); + CfgMgr::instance().commit(); EXPECT_EQ(subnet2, srv.selectSubnet(pkt)); } @@ -1938,7 +1953,8 @@ TEST_F(Dhcpv6SrvTest, relayOverride) { ASSERT_NO_THROW(configure(config)); // Let's get the subnet configuration objects - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_EQ(2, subnets->size()); // Let's get them for easy reference @@ -2014,7 +2030,8 @@ TEST_F(Dhcpv6SrvTest, relayOverrideAndClientClass) { ASSERT_NO_THROW(configure(config)); // Let's get the subnet configuration objects - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_EQ(2, subnets->size()); // Let's get them for easy reference diff --git a/src/bin/dhcp6/tests/dhcp6_test_utils.cc b/src/bin/dhcp6/tests/dhcp6_test_utils.cc index 35a8932b28..a76571538b 100644 --- a/src/bin/dhcp6/tests/dhcp6_test_utils.cc +++ b/src/bin/dhcp6/tests/dhcp6_test_utils.cc @@ -36,8 +36,9 @@ Dhcpv6SrvTest::Dhcpv6SrvTest() 64)); subnet_->addPool(pool_); - isc::dhcp::CfgMgr::instance().deleteSubnets6(); - isc::dhcp::CfgMgr::instance().addSubnet6(subnet_); + isc::dhcp::CfgMgr::instance().clear(); + isc::dhcp::CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet_); + isc::dhcp::CfgMgr::instance().commit(); // configure PD pool pd_pool_ = isc::dhcp::Pool6Ptr @@ -604,6 +605,8 @@ Dhcpv6SrvTest::configure(const std::string& config, NakedDhcpv6Srv& srv) { int rcode; ConstElementPtr comment = config::parseAnswer(rcode, status); ASSERT_EQ(0, rcode); + + CfgMgr::instance().commit(); } // Generate IA_NA option with specified parameters diff --git a/src/bin/dhcp6/tests/dhcp6_test_utils.h b/src/bin/dhcp6/tests/dhcp6_test_utils.h index 27e053992a..e59b8c5faf 100644 --- a/src/bin/dhcp6/tests/dhcp6_test_utils.h +++ b/src/bin/dhcp6/tests/dhcp6_test_utils.h @@ -348,7 +348,7 @@ public: /// /// Removes existing configuration. ~Dhcpv6SrvTest() { - isc::dhcp::CfgMgr::instance().deleteSubnets6(); + isc::dhcp::CfgMgr::instance().clear(); }; /// @brief Runs DHCPv6 configuration from the JSON string. diff --git a/src/bin/dhcp6/tests/fqdn_unittest.cc b/src/bin/dhcp6/tests/fqdn_unittest.cc index 78f65f5db2..a9f8c1731f 100644 --- a/src/bin/dhcp6/tests/fqdn_unittest.cc +++ b/src/bin/dhcp6/tests/fqdn_unittest.cc @@ -974,13 +974,14 @@ TEST_F(FqdnDhcpv6SrvTest, processRequestReuseExpiredLease) { // We are going to configure a subnet with a pool that consists of // exactly one address. This address will be handed out to the // client, will get expired and then be reused. - CfgMgr::instance().deleteSubnets6(); + CfgMgr::instance().clear(); subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1:1::"), 56, 1, 2, 3, 4)); subnet_->setIface("eth0"); pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, addr, addr)); subnet_->addPool(pool_); - CfgMgr::instance().addSubnet6(subnet_); + CfgMgr::instance().getStagingCfg()->getCfgSubnets6()->add(subnet_); + CfgMgr::instance().commit(); // Allocate a lease. testProcessMessage(DHCPV6_REQUEST, "myhost.example.com", diff --git a/src/bin/dhcp6/tests/hooks_unittest.cc b/src/bin/dhcp6/tests/hooks_unittest.cc index 5f0dca6249..cc49fb02f2 100644 --- a/src/bin/dhcp6/tests/hooks_unittest.cc +++ b/src/bin/dhcp6/tests/hooks_unittest.cc @@ -922,6 +922,8 @@ TEST_F(HooksDhcpv6SrvTest, subnet6_select) { comment_ = parseAnswer(rcode_, status); ASSERT_EQ(0, rcode_); + CfgMgr::instance().commit(); + // Prepare solicit packet. Server should select first subnet for it Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); sol->setRemoteAddr(IOAddress("fe80::abcd")); @@ -942,7 +944,8 @@ TEST_F(HooksDhcpv6SrvTest, subnet6_select) { // Check that pkt6 argument passing was successful and returned proper value EXPECT_TRUE(callback_pkt6_.get() == sol.get()); - const Subnet6Collection* exp_subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* exp_subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); // The server is supposed to pick the first subnet, because of matching // interface. Check that the value is reported properly. @@ -990,6 +993,8 @@ TEST_F(HooksDhcpv6SrvTest, subnet_select_change) { comment_ = parseAnswer(rcode_, status); ASSERT_EQ(0, rcode_); + CfgMgr::instance().commit(); + // Prepare solicit packet. Server should select first subnet for it Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); sol->setRemoteAddr(IOAddress("fe80::abcd")); @@ -1016,7 +1021,8 @@ TEST_F(HooksDhcpv6SrvTest, subnet_select_change) { ASSERT_TRUE(addr_opt); // Get all subnets and use second subnet for verification - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_EQ(2, subnets->size()); // Advertised address must belong to the second pool (in subnet's range, diff --git a/src/bin/dhcp6/tests/kea_controller_unittest.cc b/src/bin/dhcp6/tests/kea_controller_unittest.cc index 7be309ad0d..ba78cdcb42 100644 --- a/src/bin/dhcp6/tests/kea_controller_unittest.cc +++ b/src/bin/dhcp6/tests/kea_controller_unittest.cc @@ -106,7 +106,8 @@ TEST_F(JSONFileBackendTest, jsonFile) { EXPECT_NO_THROW(srv->init(TEST_FILE)); // Now check if the configuration has been applied correctly. - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_TRUE(subnets); ASSERT_EQ(3, subnets->size()); // We expect 3 subnets. @@ -176,7 +177,8 @@ TEST_F(JSONFileBackendTest, comments) { EXPECT_NO_THROW(srv->init(TEST_FILE)); // Now check if the configuration has been applied correctly. - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = + CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->getAll(); ASSERT_TRUE(subnets); ASSERT_EQ(1, subnets->size()); diff --git a/src/bin/dhcp6/tests/rebind_unittest.cc b/src/bin/dhcp6/tests/rebind_unittest.cc index ec33efb9bc..82b2dfcdc0 100644 --- a/src/bin/dhcp6/tests/rebind_unittest.cc +++ b/src/bin/dhcp6/tests/rebind_unittest.cc @@ -223,8 +223,8 @@ TEST_F(RebindTest, directClient) { // subnets. ASSERT_EQ(1, client.getLeaseNum()); Lease6 lease_client2 = client.getLease(0); - ASSERT_TRUE(CfgMgr::instance().getSubnet6(lease_client2.addr_, - ClientClasses())); + ASSERT_TRUE(CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()-> + selectSubnet(lease_client2.addr_, ClientClasses())); // The client's lease should have been extended. The client will // update the cltt to current time when the lease gets extended. ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000); @@ -337,8 +337,8 @@ TEST_F(RebindTest, relayedClient) { // subnets. ASSERT_EQ(1, client.getLeaseNum()); Lease6 lease_client2 = client.getLease(0); - ASSERT_TRUE(CfgMgr::instance().getSubnet6(lease_client2.addr_, - ClientClasses())); + ASSERT_TRUE(CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()-> + selectSubnet(lease_client2.addr_, ClientClasses())); // The client's lease should have been extended. The client will // update the cltt to current time when the lease gets extended. ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000); @@ -498,8 +498,8 @@ TEST_F(RebindTest, directClientPD) { // subnets. ASSERT_EQ(1, client.getLeaseNum()); Lease6 lease_client2 = client.getLease(0); - ASSERT_TRUE(CfgMgr::instance().getSubnet6(lease_client2.addr_, - ClientClasses())); + ASSERT_TRUE(CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()-> + selectSubnet(lease_client2.addr_, ClientClasses())); // The client's lease should have been extended. The client will // update the cltt to current time when the lease gets extended. ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000); @@ -675,8 +675,8 @@ TEST_F(RebindTest, relayedUnicast) { // subnets. ASSERT_EQ(1, client.getLeaseNum()); Lease6 lease_client2 = client.getLease(0); - ASSERT_TRUE(CfgMgr::instance().getSubnet6(lease_client2.addr_, - ClientClasses())); + ASSERT_TRUE(CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()-> + selectSubnet(lease_client2.addr_, ClientClasses())); // The client's lease should have been extended. The client will // update the cltt to current time when the lease gets extended. ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000); diff --git a/src/bin/dhcp6/tests/sarr_unittest.cc b/src/bin/dhcp6/tests/sarr_unittest.cc index 236daa5d53..e2118eb7ae 100644 --- a/src/bin/dhcp6/tests/sarr_unittest.cc +++ b/src/bin/dhcp6/tests/sarr_unittest.cc @@ -76,7 +76,8 @@ TEST_F(SARRTest, directClientPrefixHint) { client.usePD(); configure(CONFIGS[0], *client.getServer()); // Make sure we ended-up having expected number of subnets configured. - const Subnet6Collection* subnets = CfgMgr::instance().getSubnets6(); + const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()-> + getCfgSubnets6()->getAll(); ASSERT_EQ(1, subnets->size()); // Append IAPREFIX option to the client's message. ASSERT_NO_THROW(client.useHint(100, 200, 64, "2001:db8:3:33::33")); diff --git a/src/lib/dhcpsrv/cfg_subnets6.cc b/src/lib/dhcpsrv/cfg_subnets6.cc index 45b8627f27..38be135e42 100644 --- a/src/lib/dhcpsrv/cfg_subnets6.cc +++ b/src/lib/dhcpsrv/cfg_subnets6.cc @@ -49,7 +49,7 @@ CfgSubnets6::selectSubnet(const SubnetSelector& selector) const { } // If interface name didn't match, try the client's address. - if (!subnet && selector.remote_address_.isSpecified()) { + if (!subnet && selector.remote_address_ != IOAddress("::")) { subnet = selectSubnet(selector.remote_address_, selector.client_classes_); } diff --git a/src/lib/dhcpsrv/cfgmgr.cc b/src/lib/dhcpsrv/cfgmgr.cc index 2a578a2c77..632b2f63a2 100644 --- a/src/lib/dhcpsrv/cfgmgr.cc +++ b/src/lib/dhcpsrv/cfgmgr.cc @@ -62,114 +62,6 @@ CfgMgr::addOptionSpace6(const OptionSpacePtr& space) { spaces6_.insert(make_pair(space->getName(), space)); } -Subnet6Ptr -CfgMgr::getSubnet6(const std::string& iface, - const isc::dhcp::ClientClasses& classes) { - - if (!iface.length()) { - return (Subnet6Ptr()); - } - - // If there is more than one, we need to choose the proper one - for (Subnet6Collection::iterator subnet = subnets6_.begin(); - subnet != subnets6_.end(); ++subnet) { - - // If client is rejected because of not meeting client class criteria... - if (!(*subnet)->clientSupported(classes)) { - continue; - } - - if (iface == (*subnet)->getIface()) { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, - DHCPSRV_CFGMGR_SUBNET6_IFACE) - .arg((*subnet)->toText()).arg(iface); - return (*subnet); - } - } - return (Subnet6Ptr()); -} - -Subnet6Ptr -CfgMgr::getSubnet6(const isc::asiolink::IOAddress& hint, - const isc::dhcp::ClientClasses& classes, - const bool relay) { - - // If there is more than one, we need to choose the proper one - for (Subnet6Collection::iterator subnet = subnets6_.begin(); - subnet != subnets6_.end(); ++subnet) { - - // If client is rejected because of not meeting client class criteria... - if (!(*subnet)->clientSupported(classes)) { - continue; - } - - // If the hint is a relay address, and there is relay info specified - // for this subnet and those two match, then use this subnet. - if (relay && ((*subnet)->getRelayInfo().addr_ == hint) ) { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, - DHCPSRV_CFGMGR_SUBNET6_RELAY) - .arg((*subnet)->toText()).arg(hint.toText()); - return (*subnet); - } - - if ((*subnet)->inRange(hint)) { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_SUBNET6) - .arg((*subnet)->toText()).arg(hint.toText()); - return (*subnet); - } - } - - // sorry, we don't support that subnet - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_NO_SUBNET6) - .arg(hint.toText()); - return (Subnet6Ptr()); -} - -Subnet6Ptr CfgMgr::getSubnet6(OptionPtr iface_id_option, - const isc::dhcp::ClientClasses& classes) { - if (!iface_id_option) { - return (Subnet6Ptr()); - } - - // Let's iterate over all subnets and for those that have interface-id - // defined, check if the interface-id is equal to what we are looking for - for (Subnet6Collection::iterator subnet = subnets6_.begin(); - subnet != subnets6_.end(); ++subnet) { - - // If client is rejected because of not meeting client class criteria... - if (!(*subnet)->clientSupported(classes)) { - continue; - } - - if ( (*subnet)->getInterfaceId() && - ((*subnet)->getInterfaceId()->equals(iface_id_option))) { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, - DHCPSRV_CFGMGR_SUBNET6_IFACE_ID) - .arg((*subnet)->toText()); - return (*subnet); - } - } - return (Subnet6Ptr()); -} - -void CfgMgr::addSubnet6(const Subnet6Ptr& subnet) { - /// @todo: Check that this new subnet does not cross boundaries of any - /// other already defined subnet. - /// @todo: Check that there is no subnet with the same interface-id - if (isDuplicate(*subnet)) { - isc_throw(isc::dhcp::DuplicateSubnetID, "ID of the new IPv6 subnet '" - << subnet->getID() << "' is already in use"); - } - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_ADD_SUBNET6) - .arg(subnet->toText()); - subnets6_.push_back(subnet); -} - -void CfgMgr::deleteSubnets6() { - LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_DELETE_SUBNET6); - subnets6_.clear(); -} - std::string CfgMgr::getDataDir() { return (datadir_); diff --git a/src/lib/dhcpsrv/cfgmgr.h b/src/lib/dhcpsrv/cfgmgr.h index 43e3dc1168..77d8fd996a 100644 --- a/src/lib/dhcpsrv/cfgmgr.h +++ b/src/lib/dhcpsrv/cfgmgr.h @@ -126,97 +126,6 @@ public: return (spaces6_); } - /// @brief get IPv6 subnet by address - /// - /// Finds a matching subnet, based on an address. This can be used - /// in two cases: when trying to find an appropriate lease based on - /// a) relay link address (that must be the address that is on link) - /// b) our global address on the interface the message was received on - /// (for directly connected clients) - /// - /// If there are any classes specified in a subnet, that subnet - /// will be selected only if the client belongs to appropriate class. - /// - /// @note The client classification is checked before any relay - /// information checks are conducted. - /// - /// If relay is true then relay info overrides (i.e. value the sysadmin - /// can configure in Dhcp6/subnet6[X]/relay/ip-address) can be used. - /// That is applicable only for relays. Those overrides must not be used - /// for client address or for client hints. They are for link-addr field - /// in the RELAY_FORW message only. - /// - /// @param hint an address that belongs to a searched subnet - /// @param classes classes the client belongs to - /// @param relay true if address specified in hint is a relay - /// - /// @return a subnet object (or NULL if no suitable match was fount) - Subnet6Ptr getSubnet6(const isc::asiolink::IOAddress& hint, - const isc::dhcp::ClientClasses& classes, - const bool relay = false); - - /// @brief get IPv6 subnet by interface name - /// - /// Finds a matching local subnet, based on interface name. This - /// is used for selecting subnets that were explicitly marked by the - /// user as reachable over specified network interface. - /// - /// If there are any classes specified in a subnet, that subnet - /// will be selected only if the client belongs to appropriate class. - /// - /// @param iface_name interface name - /// @param classes classes the client belongs to - /// - /// @return a subnet object (or NULL if no suitable match was fount) - Subnet6Ptr getSubnet6(const std::string& iface_name, - const isc::dhcp::ClientClasses& classes); - - /// @brief get IPv6 subnet by interface-id - /// - /// Another possibility to find a subnet is based on interface-id. - /// - /// If there are any classes specified in a subnet, that subnet - /// will be selected only if the client belongs to appropriate class. - /// - /// @param interface_id content of interface-id option returned by a relay - /// @param classes classes the client belongs to - /// - /// @return a subnet object - Subnet6Ptr getSubnet6(OptionPtr interface_id, - const isc::dhcp::ClientClasses& classes); - - /// @brief adds an IPv6 subnet - /// - /// @param subnet new subnet to be added. - void addSubnet6(const Subnet6Ptr& subnet); - - /// @todo: Add subnet6 removal routines. Currently it is not possible - /// to remove subnets. The only case where subnet6 removal would be - /// needed is a dynamic server reconfiguration - a use case that is not - /// planned to be supported any time soon. - - /// @brief removes all IPv6 subnets - /// - /// This method removes all existing IPv6 subnets. It is used during - /// reconfiguration - old configuration is wiped and new definitions - /// are used to recreate subnets. - /// - /// @todo Implement more intelligent approach. Note that comparison - /// between old and new configuration is tricky. For example: is - /// 2000::/64 and 2000::/48 the same subnet or is it something - /// completely new? - void deleteSubnets6(); - - /// @brief returns const reference to all subnets6 - /// - /// This is used in a hook (subnet6_select), where the hook is able - /// to choose a different subnet. Server code has to offer a list - /// of possible choices (i.e. all subnets). - /// @return a pointer to const Subnet6 collection - const Subnet6Collection* getSubnets6() { - return (&subnets6_); - } - /// @brief returns path do the data directory /// /// This method returns a path to writeable directory that DHCP servers diff --git a/src/lib/dhcpsrv/srv_config.cc b/src/lib/dhcpsrv/srv_config.cc index dfaf1ddda2..e68847466a 100644 --- a/src/lib/dhcpsrv/srv_config.cc +++ b/src/lib/dhcpsrv/srv_config.cc @@ -51,7 +51,7 @@ SrvConfig::getConfigSummary(const uint32_t selection) const { } if ((selection & CFGSEL_SUBNET6) == CFGSEL_SUBNET6) { - subnets_num = CfgMgr::instance().getSubnets6()->size(); + subnets_num = getCfgSubnets6()->getAll()->size(); if (subnets_num > 0) { s << "added IPv6 subnets: " << subnets_num; } else { diff --git a/src/lib/dhcpsrv/subnet_selector.h b/src/lib/dhcpsrv/subnet_selector.h index 8fef4b6c2f..ef189dc407 100644 --- a/src/lib/dhcpsrv/subnet_selector.h +++ b/src/lib/dhcpsrv/subnet_selector.h @@ -18,7 +18,6 @@ #include #include #include -#include #include namespace isc { @@ -47,9 +46,9 @@ struct SubnetSelector { //@} /// @brief Address on which the message was received. - util::OptionalValue local_address_; + asiolink::IOAddress local_address_; /// @brief Source address of the message. - util::OptionalValue remote_address_; + asiolink::IOAddress remote_address_; /// @brief Classes that the client belongs to. ClientClasses client_classes_; /// @brief Name of the interface on which the message was received. @@ -63,8 +62,8 @@ struct SubnetSelector { giaddr_(asiolink::IOAddress("0.0.0.0")), interface_id_(), first_relay_linkaddr_(asiolink::IOAddress("::")), - local_address_(asiolink::IOAddress("0.0.0.0"), false), - remote_address_(asiolink::IOAddress("0.0.0.0"), false), + local_address_(asiolink::IOAddress("0.0.0.0")), + remote_address_(asiolink::IOAddress("0.0.0.0")), client_classes_(), iface_name_(std::string()) { } }; diff --git a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc index 5f41663897..0388cbada9 100644 --- a/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc +++ b/src/lib/dhcpsrv/tests/alloc_engine_unittest.cc @@ -91,6 +91,8 @@ public: /// in many tests, initializes cfg_mgr configuration and creates /// lease database. AllocEngine6Test() { + CfgMgr::instance().clear(); + duid_ = DuidPtr(new DUID(vector(8, 0x42))); iaid_ = 42; @@ -115,7 +117,6 @@ public: void initSubnet(const IOAddress& subnet, const IOAddress& pool_start, const IOAddress& pool_end) { CfgMgr& cfg_mgr = CfgMgr::instance(); - cfg_mgr.deleteSubnets6(); subnet_ = Subnet6Ptr(new Subnet6(subnet, 56, 1, 2, 3, 4)); pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, pool_start, pool_end)); @@ -125,7 +126,8 @@ public: pd_pool_ = Pool6Ptr(new Pool6(Lease::TYPE_PD, subnet, 56, 64)); subnet_->addPool(pd_pool_); - cfg_mgr.addSubnet6(subnet_); + cfg_mgr.getStagingCfg()->getCfgSubnets6()->add(subnet_); + cfg_mgr.commit(); } @@ -855,13 +857,13 @@ TEST_F(AllocEngine6Test, outOfAddresses6) { IOAddress addr("2001:db8:1::ad"); CfgMgr& cfg_mgr = CfgMgr::instance(); - cfg_mgr.deleteSubnets6(); // Get rid of the default test configuration + cfg_mgr.clear(); // Get rid of the default test configuration // Create configuration similar to other tests, but with a single address pool subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4)); pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, addr, addr)); // just a single address subnet_->addPool(pool_); - cfg_mgr.addSubnet6(subnet_); + cfg_mgr.getStagingCfg()->getCfgSubnets6()->add(subnet_); // Just a different duid DuidPtr other_duid = DuidPtr(new DUID(vector(12, 0xff))); @@ -939,13 +941,14 @@ TEST_F(AllocEngine6Test, requestReuseExpiredLease6) { IOAddress addr("2001:db8:1::ad"); CfgMgr& cfg_mgr = CfgMgr::instance(); - cfg_mgr.deleteSubnets6(); // Get rid of the default test configuration + cfg_mgr.clear(); // Get rid of the default test configuration // Create configuration similar to other tests, but with a single address pool subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4)); pool_ = Pool6Ptr(new Pool6(Lease::TYPE_NA, addr, addr)); // just a single address subnet_->addPool(pool_); - cfg_mgr.addSubnet6(subnet_); + cfg_mgr.getStagingCfg()->getCfgSubnets6()->add(subnet_); + cfg_mgr.commit(); // Let's create an expired lease DuidPtr other_duid = DuidPtr(new DUID(vector(12, 0xff))); diff --git a/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc b/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc index 0c3008ba02..cdce00572d 100644 --- a/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc @@ -283,7 +283,6 @@ public: void clear() { CfgMgr::instance().setVerbose(false); - CfgMgr::instance().deleteSubnets6(); CfgMgr::instance().clear(); } @@ -304,307 +303,6 @@ TEST_F(CfgMgrTest, configuration) { EXPECT_TRUE(configuration->getLoggingInfo().empty()); } -// This test verifies if the configuration manager is able to hold v6 subnets -// with their relay address information and return proper subnets, based on -// those addresses. -TEST_F(CfgMgrTest, subnet6RelayOverride) { - CfgMgr& cfg_mgr = CfgMgr::instance(); - - // Let's configure 3 subnets - Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4)); - - cfg_mgr.addSubnet6(subnet1); - cfg_mgr.addSubnet6(subnet2); - cfg_mgr.addSubnet6(subnet3); - - // Check that without relay-info specified, subnets are not selected - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::1"), classify_, true)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::2"), classify_, true)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::3"), classify_, true)); - - // Now specify relay info - subnet1->setRelayInfo(IOAddress("2001:db8:ff::1")); - subnet2->setRelayInfo(IOAddress("2001:db8:ff::2")); - subnet3->setRelayInfo(IOAddress("2001:db8:ff::3")); - - // And try again. This time relay-info is there and should match. - EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::1"), classify_, true)); - EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::2"), classify_, true)); - EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::3"), classify_, true)); - - // Finally, check that the relay works only if hint provided is relay address - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::1"), classify_, false)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::2"), classify_, false)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2001:db8:ff::3"), classify_, false)); -} - - -// This test verifies if the configuration manager is able to hold and return -// valid leases -TEST_F(CfgMgrTest, classifySubnet6) { - CfgMgr& cfg_mgr = CfgMgr::instance(); - - // Let's configure 3 subnets - Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4)); - - cfg_mgr.addSubnet6(subnet1); - cfg_mgr.addSubnet6(subnet2); - cfg_mgr.addSubnet6(subnet3); - - // Let's sanity check that we can use that configuration. - EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); - EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_)); - EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_)); - - // Client now belongs to bar class. - classify_.insert("bar"); - - // There are no class restrictions defined, so everything should work - // as before - EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); - EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_)); - EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_)); - - // Now let's add client class restrictions. - subnet1->allowClientClass("foo"); // Serve here only clients from foo class - subnet2->allowClientClass("bar"); // Serve here only clients from bar class - subnet3->allowClientClass("baz"); // Serve here only clients from baz class - - // The same check as above should result in client being served only in - // bar class, i.e. subnet2 - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); - EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_)); - - // Now let's check that client with wrong class is not supported - classify_.clear(); - classify_.insert("some_other_class"); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_)); - - // Finally, let's check that client without any classes is not supported - classify_.clear(); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_)); -} - -// This test verifies if the configuration manager is able to hold, select -// and return valid subnets, based on interface names along with client -// classification. -TEST_F(CfgMgrTest, classifySubnet6Interface) { - CfgMgr& cfg_mgr = CfgMgr::instance(); - - // Let's have an odd configuration: 3 shared subnets available on the - // same direct link. - Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4)); - subnet1->setIface("foo"); - subnet2->setIface("foo"); - subnet3->setIface("foo"); - cfg_mgr.addSubnet6(subnet1); - cfg_mgr.addSubnet6(subnet2); - cfg_mgr.addSubnet6(subnet3); - - - // Regular client should get the first subnet, because it meets all - // criteria (matching interface name, no class restrictions. - EXPECT_EQ(subnet1, cfg_mgr.getSubnet6("foo", classify_)); - - // Now let's add class requirements for subnet1 - subnet1->allowClientClass("alpha"); - - // Client should now get the subnet2, because he no longer meets - // requirements for subnet1 (belongs to wrong class) - EXPECT_EQ(subnet2, cfg_mgr.getSubnet6("foo", classify_)); - - // Now let's add (not matching) classes to the other two subnets - subnet2->allowClientClass("beta"); - subnet3->allowClientClass("gamma"); - - // No subnets are suitable, so nothing will be selected - EXPECT_FALSE(cfg_mgr.getSubnet6("foo", classify_)); - - // Ok, let's add the client to gamme class, so he'll get a subnet - classify_.insert("gamma"); - EXPECT_EQ(subnet3, cfg_mgr.getSubnet6("foo", classify_)); -} - -// This test verifies if the configuration manager is able to hold, select -// and return valid subnets, based on interface-id option inserted by relay, -// along with client classification. -TEST_F(CfgMgrTest, classifySubnet6InterfaceId) { - CfgMgr& cfg_mgr = CfgMgr::instance(); - - // Let's have an odd configuration: 3 shared subnets available via the - // same remote relay with the same interface-id. - Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4)); - OptionPtr ifaceid = generateInterfaceId("relay1.eth0"); - subnet1->setInterfaceId(ifaceid); - subnet2->setInterfaceId(ifaceid); - subnet3->setInterfaceId(ifaceid); - cfg_mgr.addSubnet6(subnet1); - cfg_mgr.addSubnet6(subnet2); - cfg_mgr.addSubnet6(subnet3); - - // Regular client should get the first subnet, because it meets all - // criteria (matching interface name, no class restrictions. - EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(ifaceid, classify_)); - - // Now let's add class requirements for subnet1 - subnet1->allowClientClass("alpha"); - - // Client should now get the subnet2, because he no longer meets - // requirements for subnet1 (belongs to wrong class) - EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(ifaceid, classify_)); - - // Now let's add (not matching) classes to the other two subnets - subnet2->allowClientClass("beta"); - subnet3->allowClientClass("gamma"); - - // No subnets are suitable, so nothing will be selected - EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid, classify_)); - - // Ok, let's add the client to gamme class, so he'll get a subnet - classify_.insert("gamma"); - EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(ifaceid, classify_)); -} - -// This test verifies if the configuration manager is able to hold and return -// valid leases -TEST_F(CfgMgrTest, subnet6) { - CfgMgr& cfg_mgr = CfgMgr::instance(); - - Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4)); - - // There shouldn't be any subnet configured at this stage - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::1"), classify_)); - - cfg_mgr.addSubnet6(subnet1); - - // Now we have only one subnet, any request will be served from it - EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2000::1"), classify_)); - - // We used to allow getting a sole subnet if there was only one subnet - // configured. That is no longer true. The code should not return - // a subnet. - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("fe80::dead:beef"), classify_)); - - cfg_mgr.addSubnet6(subnet2); - cfg_mgr.addSubnet6(subnet3); - - EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("4000::123"), classify_)); - EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::dead:beef"), - classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("5000::1"), classify_)); - - // Check that deletion of the subnets works. - cfg_mgr.deleteSubnets6(); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("3000::123"), classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::123"), classify_)); -} - -// This test verifies if the configuration manager is able to hold, select -// and return valid subnets, based on interface names. -TEST_F(CfgMgrTest, subnet6Interface) { - CfgMgr& cfg_mgr = CfgMgr::instance(); - - Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4)); - subnet1->setIface("foo"); - subnet2->setIface("bar"); - subnet3->setIface("foobar"); - - // There shouldn't be any subnet configured at this stage - EXPECT_FALSE(cfg_mgr.getSubnet6("foo", classify_)); - - cfg_mgr.addSubnet6(subnet1); - - // Now we have only one subnet, any request will be served from it - EXPECT_EQ(subnet1, cfg_mgr.getSubnet6("foo", classify_)); - - // Check that the interface name is checked even when there is - // only one subnet defined. - EXPECT_FALSE(cfg_mgr.getSubnet6("bar", classify_)); - - // We used to allow getting a sole subnet if there was only one subnet - // configured. That is no longer true. The code should not return - // a subnet. - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("fe80::dead:beef"), classify_)); - - cfg_mgr.addSubnet6(subnet2); - cfg_mgr.addSubnet6(subnet3); - - EXPECT_EQ(subnet3, cfg_mgr.getSubnet6("foobar", classify_)); - EXPECT_EQ(subnet2, cfg_mgr.getSubnet6("bar", classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6("xyzzy", classify_)); // no such interface - - // Check that deletion of the subnets works. - cfg_mgr.deleteSubnets6(); - EXPECT_FALSE(cfg_mgr.getSubnet6("foo", classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6("bar", classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6("foobar", classify_)); -} - -// This test verifies if the configuration manager is able to hold, select -// and return valid leases, based on interface-id option values -TEST_F(CfgMgrTest, subnet6InterfaceId) { - CfgMgr& cfg_mgr = CfgMgr::instance(); - - Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4)); - Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4)); - - // interface-id options used in subnets 1,2, and 3 - OptionPtr ifaceid1 = generateInterfaceId("relay1.eth0"); - OptionPtr ifaceid2 = generateInterfaceId("VL32"); - // That's a strange interface-id, but this is a real life example - OptionPtr ifaceid3 = generateInterfaceId("ISAM144|299|ipv6|nt:vp:1:110"); - - // bogus interface-id - OptionPtr ifaceid_bogus = generateInterfaceId("non-existent"); - - subnet1->setInterfaceId(ifaceid1); - subnet2->setInterfaceId(ifaceid2); - subnet3->setInterfaceId(ifaceid3); - - // There shouldn't be any subnet configured at this stage - EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid1, classify_)); - - cfg_mgr.addSubnet6(subnet1); - - // If we have only a single subnet and the request came from a local - // address, let's use that subnet - EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(ifaceid1, classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid2, classify_)); - - cfg_mgr.addSubnet6(subnet2); - cfg_mgr.addSubnet6(subnet3); - - EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(ifaceid3, classify_)); - EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(ifaceid2, classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid_bogus, classify_)); - - // Check that deletion of the subnets works. - cfg_mgr.deleteSubnets6(); - EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid1, classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid2, classify_)); - EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid3, classify_)); -} - - // This test verifies that new DHCPv4 option spaces can be added to // the configuration manager and that duplicated option space is // rejected. @@ -731,26 +429,6 @@ TEST_F(CfgMgrTest, d2ClientConfig) { EXPECT_NE(*original_config, *updated_config); } -// Checks that detection of duplicated subnet IDs works as expected. It should -// not be possible to add two IPv6 subnets holding the same ID to the config -// manager. -TEST_F(CfgMgrTest, subnet6Duplication) { - CfgMgr& cfg_mgr = CfgMgr::instance(); - - Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 64, 1, 2, 3, - 4, 123)); - Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 64, 1, 2, 3, - 4, 124)); - Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 64, 1, 2, 3, - 4, 123)); - - ASSERT_NO_THROW(cfg_mgr.addSubnet6(subnet1)); - EXPECT_NO_THROW(cfg_mgr.addSubnet6(subnet2)); - // Subnet 3 has the same ID as subnet 1. It shouldn't be able to add it. - EXPECT_THROW(cfg_mgr.addSubnet6(subnet3), isc::dhcp::DuplicateSubnetID); -} - - // This test verifies that the configuration staging, commit and rollback works // as expected. TEST_F(CfgMgrTest, staging) { diff --git a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc index 1e1326e359..d92886fd72 100644 --- a/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc +++ b/src/lib/dhcpsrv/tests/dhcp_parsers_unittest.cc @@ -447,7 +447,6 @@ public: void reset_context(){ // Note set context universe to V6 as it has to be something. CfgMgr::instance().clear(); - CfgMgr::instance().deleteSubnets6(); parser_context_.reset(new ParserContext(Option::V6)); // Ensure no hooks libraries are loaded. diff --git a/src/lib/dhcpsrv/tests/srv_config_unittest.cc b/src/lib/dhcpsrv/tests/srv_config_unittest.cc index 45945d69f4..cfe2e0cd2f 100644 --- a/src/lib/dhcpsrv/tests/srv_config_unittest.cc +++ b/src/lib/dhcpsrv/tests/srv_config_unittest.cc @@ -41,8 +41,6 @@ public: /// is @c TEST_SUBNETS_NUM for IPv4 and IPv6 each. SrvConfigTest() : iface_mgr_test_config_(true) { - // Remove any subnets dangling from previous unit tests. - clearSubnets(); // Disable DDNS. enableDDNS(false); @@ -74,10 +72,7 @@ public: } /// @brief Destructor. - /// - /// Removes any dangling configuration. virtual ~SrvConfigTest() { - clearSubnets(); } /// @brief Convenience function which adds IPv4 subnet to the configuration. @@ -108,12 +103,6 @@ public: /// @c conf_ object. void addSubnet6(const unsigned int index); - /// @brief Removes all subnets from the configuration. - /// - /// @todo Modify this function once the subnet configuration is migrated - /// from @c CfgMgr to @c SrvConfig. - void clearSubnets(); - /// @brief Enable/disable DDNS. /// /// @param enable A boolean value indicating if the DDNS should be @@ -146,12 +135,7 @@ SrvConfigTest::addSubnet6(const unsigned int index) { FAIL() << "Subnet index " << index << "out of range (0.." << TEST_SUBNETS_NUM << "): " << "unable to add IPv6 subnet"; } - CfgMgr::instance().addSubnet6(test_subnets6_[index]); -} - -void -SrvConfigTest::clearSubnets() { - CfgMgr::instance().deleteSubnets6(); + conf_.getCfgSubnets6()->add(test_subnets6_[index]); } void