void
CfgSubnets6::merge(CfgOptionDefPtr cfg_def, CfgSharedNetworks6Ptr networks,
CfgSubnets6& other) {
- auto& index = subnets_.get<SubnetSubnetIdIndexTag>();
+ auto& index_id = subnets_.get<SubnetSubnetIdIndexTag>();
+ auto& index_prefix = subnets_.get<SubnetPrefixIndexTag>();
// Iterate over the subnets to be merged. They will replace the existing
// subnets with the same id. All new subnets will be inserted into the
++other_subnet) {
// Check if there is a subnet with the same ID.
- auto subnet_it = index.find((*other_subnet)->getID());
- if (subnet_it != index.end()) {
+ auto subnet_it = index_id.find((*other_subnet)->getID());
+ if (subnet_it != index_id.end()) {
// Subnet found.
auto existing_subnet = *subnet_it;
}
// Now we remove the existing subnet.
- index.erase(subnet_it);
+ index_id.erase(subnet_it);
+ }
+
+ // Check if there is a subnet with the same prefix.
+ auto subnet_prefix_it = index_prefix.find((*other_subnet)->toText());
+ if (subnet_prefix_it != index_prefix.end()) {
+
+ // Subnet found.
+ auto existing_subnet = *subnet_prefix_it;
+
+ // Updating the id can lead to problems... e.g. reservation
+ // for the previous subnet ID.
+ // @todo: check reservations
+
+ // We're going to replace the existing subnet with the other
+ // version. If it belongs to a shared network, we need
+ // remove it from that network.
+ SharedNetwork6Ptr network;
+ existing_subnet->getSharedNetwork(network);
+ if (network) {
+ network->del(existing_subnet->getID());
+ }
+
+ // Now we remove the existing subnet.
+ index_prefix.erase(subnet_prefix_it);
}
// Create the subnet's options based on the given definitions.
SubnetID(4), 100, shared_network2));
// Fill cfg_from configuration with subnets.
- // subnet 1b updates subnet 1 but leaves it in network 1
- Subnet6Ptr subnet1b(new Subnet6(IOAddress("2001:1::"),
+ // subnet 1b updates subnet 1 but leaves it in network 1 with the same ID.
+ Subnet6Ptr subnet1b(new Subnet6(IOAddress("2001:10::"),
64, 2, 3, 100, 400, SubnetID(1)));
subnet1b->setSharedNetworkName("shared-network1");
option->setData(value.begin(), value.end());
ASSERT_NO_THROW(subnet1b->getCfgOption()->add(option, false, "isc"));
- // subnet 3b updates subnet 3 and removes it from network 2
+ // subnet 3b updates subnet 3 with different UD and removes it
+ // from network 2
Subnet6Ptr subnet3b(new Subnet6(IOAddress("2001:3::"),
- 64, 3, 4, 100, 500, SubnetID(3)));
+ 64, 3, 4, 100, 500, SubnetID(30)));
// Now Add generic option 1 to subnet 3b.
value = "Team!";
ASSERT_EQ(5, cfg_to.getAll()->size());
// The subnet1 should be replaced by subnet1b.
- ASSERT_NO_FATAL_FAILURE(checkMergedSubnet(cfg_to, "2001:1::/64",
+ ASSERT_NO_FATAL_FAILURE(checkMergedSubnet(cfg_to, "2001:10::/64",
SubnetID(1), 400, shared_network1));
// Let's verify that our option is there and populated correctly.
- auto subnet = cfg_to.getByPrefix("2001:1::/64");
+ auto subnet = cfg_to.getByPrefix("2001:10::/64");
auto desc = subnet->getCfgOption()->get("isc", 1);
ASSERT_TRUE(desc.option_);
OptionStringPtr opstr = boost::dynamic_pointer_cast<OptionString>(desc.option_);
// subnet3 should be replaced by subnet3b and no longer assigned to a network.
ASSERT_NO_FATAL_FAILURE(checkMergedSubnet(cfg_to, "2001:3::/64",
- SubnetID(3), 500, no_network));
+ SubnetID(30), 500, no_network));
// Let's verify that our option is there and populated correctly.
subnet = cfg_to.getByPrefix("2001:3::/64");
desc = subnet->getCfgOption()->get("isc", 1);