2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-29 13:07:50 +00:00

[#1405] merged second pass

This commit is contained in:
Razvan Becheriu 2020-11-11 19:06:06 +02:00
parent 8d05ba02b2
commit d26a72f560
26 changed files with 881 additions and 951 deletions

View File

@ -766,6 +766,52 @@ insert into hosts(dhcp_identifier, dhcp_identifier_type, dhcp4_subnet_id, ipv4_a
ERRCODE=$?
assert_eq 0 $ERRCODE "insert into hosts failed, expected exit code %d, actual %d"
# Schema upgrade from 9.4 to 9.5.
# table: dhcp4_shared_network (reservation_mode replaced by reservations flags)
qry="select reservations_global, reservations_in_subnet, reservations_out_of_pool from dhcp4_shared_network"
run_statement "dhcp4_shared_network" "$qry"
qry="show columns from dhcp4_shared_network like 'reservation_mode'";
text=`mysql_execute "${qry}"`
ERRCODE=$?
assert_eq 0 $ERRCODE "show columns from dhcp4_shared_network like 'reservation_mode' failed. (expected status code %d, returned %d)"
count=`echo $text | grep -ic reservation`
assert_eq $count 0 "dhcp4_shared_network has still reservation_mode column. (returned count %d, expected %d)"
# table: dhcp4_subnet (reservation_mode replaced by reservations flags)
qry="select reservations_global, reservations_in_subnet, reservations_out_of_pool from dhcp4_subnet"
run_statement "dhcp4_subnet" "$qry"
qry="show columns from dhcp4_subnet like 'reservation_mode'";
text=`mysql_execute "${qry}"`
ERRCODE=$?
assert_eq 0 $ERRCODE "show columns from dhcp4_subnet like 'reservation_mode' failed. (expected status code %d, returned %d)"
count=`echo $text | grep -ic reservation`
assert_eq $count 0 "dhcp4_subnet has still reservation_mode column. (returned count %d, expected %d)"
# table: dhcp6_shared_network (reservation_mode replaced by reservations flags)
qry="select reservations_global, reservations_in_subnet, reservations_out_of_pool from dhcp6_shared_network"
run_statement "dhcp6_shared_network" "$qry"
qry="show columns from dhcp6_shared_network like 'reservation_mode'";
text=`mysql_execute "${qry}"`
ERRCODE=$?
assert_eq 0 $ERRCODE "show columns from dhcp6_shared_network like 'reservation_mode' failed. (expected status code %d, returned %d)"
count=`echo $text | grep -ic reservation`
assert_eq $count 0 "dhcp6_shared_network has still reservation_mode column. (returned count %d, expected %d)"
# table: dhcp6_subnet (reservation_mode replaced by reservations flags)
qry="select reservations_global, reservations_in_subnet, reservations_out_of_pool from dhcp6_subnet"
run_statement "dhcp6_subnet" "$qry"
qry="show columns from dhcp6_subnet like 'reservation_mode'";
text=`mysql_execute "${qry}"`
ERRCODE=$?
assert_eq 0 $ERRCODE "show columns from dhcp6_subnet like 'reservation_mode' failed. (expected status code %d, returned %d)"
count=`echo $text | grep -ic reservation`
assert_eq $count 0 "dhcp6_subnet has still reservation_mode column. (returned count %d, expected %d)"
# Verify upgraded schema reports version 9.5
version=$(${keaadmin} db-version mysql -u $db_user -p $db_password -n $db_name -d $db_scripts_dir)
assert_str_eq "9.5" ${version} "Expected kea-admin to return %s, returned value was %s"
@ -1352,7 +1398,7 @@ mysql_unused_subnet_id_test() {
# Verifies that you can upgrade from an earlier version and
# that reservation_mode values in subnet and shared network tables are
# converted to new values.
# converted to new reservations flags.
mysql_reservation_mode_upgrade_test() {
test_start "mysql_reservation_mode_upgrade_test"
@ -1422,68 +1468,68 @@ mysql_reservation_mode_upgrade_test() {
# Upgrade to schema 9.5.
mysql_upgrade_schema_to_version 9.5
# Test DISABLED (0) -> 0
qry="select count(id) from dhcp4_shared_network where reservation_mode = 0 and name = 'test0';"
# Test DISABLED (0) -> false, false, false
qry="select count(id) from dhcp4_shared_network where reservations_global = false and reservations_in_subnet = false and reservations_out_of_pool = false and name = 'test0';"
run_statement "#4_shared_disabled" "$qry" 1
# Test OUT_OF_POOL (1) -> 3
qry="select count(id) from dhcp4_shared_network where reservation_mode = 3 and name = 'test1';"
# Test OUT_OF_POOL (1) -> false, true, true
qry="select count(id) from dhcp4_shared_network where reservations_global = false and reservations_in_subnet = true and reservations_out_of_pool = true and name = 'test1';"
run_statement "#4_shared_out_of_pool" "$qry" 1
# Test GLOBAL (2) -> 4
qry="select count(id) from dhcp4_shared_network where reservation_mode = 4 and name = 'test2';"
# Test GLOBAL (2) -> true, false, false
qry="select count(id) from dhcp4_shared_network where reservations_global = true and reservations_in_subnet = false and reservations_out_of_pool = false and name = 'test2';"
run_statement "#4_shared_global" "$qry" 1
# Test ALL (3) -> 2
qry="select count(id) from dhcp4_shared_network where reservation_mode = 2 and name = 'test3';"
# Test ALL (3) -> false, true, false
qry="select count(id) from dhcp4_shared_network where reservation_global = false and reservations_in_subnet = true and reservations_out_of_pool = false name = 'test3';"
run_statement "#4_shared_all" "$qry" 1
# Test DISABLED (0) -> 0
qry="select count(subnet_id) from dhcp4_subnet where reservation_mode = 0 and subnet_prefix = '192.0.0.0/24'"
# Test DISABLED (0) -> false, false, false
qry="select count(subnet_id) from dhcp4_subnet where reservations_global = false and reservations_in_subnet = false and reservations_out_of_pool = false and subnet_prefix = '192.0.0.0/24'"
run_statement "#4_subnet_disabled" "$qry" 1
# Test OUT_OF_POOL (1) -> 3
qry="select count(subnet_id) from dhcp4_subnet where reservation_mode = 3 and subnet_prefix = '192.0.1.0/24'"
# Test OUT_OF_POOL (1) -> false, true, true
qry="select count(subnet_id) from dhcp4_subnet where reservations_global = false and reservations_in_subnet = true and reservations_out_of_pool = true and subnet_prefix = '192.0.1.0/24'"
run_statement "#4_subnet_out_of_pool" "$qry" 1
# Test GLOBAL (2) -> 4
qry="select count(subnet_id) from dhcp4_subnet where reservation_mode = 4 and subnet_prefix = '192.0.2.0/24'"
# Test GLOBAL (2) -> true, false, false
qry="select count(subnet_id) from dhcp4_subnet where reservations_global = true and reservations_in_subnet = false and reservations_out_of_pool = false and subnet_prefix = '192.0.2.0/24'"
run_statement "#4_subnet_global" "$qry" 1
# Test ALL (3) -> 2
qry="select count(subnet_id) from dhcp4_subnet where reservation_mode = 2 and subnet_prefix = '192.0.3.0/24'"
# Test ALL (3) -> false, true, false
qry="select count(subnet_id) from dhcp4_subnet where reservations_global = false and reservations_in_subnet = true and reservations_out_of_pool = false and subnet_prefix = '192.0.3.0/24'"
run_statement "#4_subnet_all" "$qry" 1
# Test DISABLED (0) -> 0
qry="select count(id) from dhcp6_shared_network where reservation_mode = 0 and name = 'test0';"
# Test DISABLED (0) -> false, false, false
qry="select count(id) from dhcp6_shared_network where reservations_global = false and reservations_in_subnet = false and reservations_out_of_pool = false and name = 'test0';"
run_statement "#6_shared_disabled" "$qry" 1
# Test OUT_OF_POOL (1) -> 3
qry="select count(id) from dhcp6_shared_network where reservation_mode = 3 and name = 'test1';"
# Test OUT_OF_POOL (1) -> false, true, true
qry="select count(id) from dhcp6_shared_network where reservations_global = false and reservations_in_subnet = true and reservations_out_of_pool = true and name = 'test1';"
run_statement "#6_shared_out_of_pool" "$qry" 1
# Test GLOBAL (2) -> 4
qry="select count(id) from dhcp6_shared_network where reservation_mode = 4 and name = 'test2';"
# Test GLOBAL (2) -> true, false, false
qry="select count(id) from dhcp6_shared_network where reservations_global = true and reservations_in_subnet = false and reservations_out_of_pool = false and name = 'test2';"
run_statement "#6_shared_global" "$qry" 1
# Test ALL (3) -> 2
qry="select count(id) from dhcp6_shared_network where reservation_mode = 2 and name = 'test3';"
# Test ALL (3) -> false, true, false
qry="select count(id) from dhcp6_shared_network where reservations_global = false and reservations_in_subnet = true and reservations_out_of_pool = false and name = 'test3';"
run_statement "#6_shared_all" "$qry" 1
# Test DISABLED (0) -> 0
qry="select count(subnet_id) from dhcp6_subnet where reservation_mode = 0 and subnet_prefix = '2001:db8::/64'"
# Test DISABLED (0) -> false, false, false
qry="select count(subnet_id) from dhcp6_subnet where reservations_global = false and reservations_in_subnet = false and reservations_out_of_pool = false and subnet_prefix = '2001:db8::/64'"
run_statement "#6_subnet_disabled" "$qry" 1
# Test OUT_OF_POOL (1) -> 3
qry="select count(subnet_id) from dhcp6_subnet where reservation_mode = 3 and subnet_prefix = '2001:db8:1::/64'"
# Test OUT_OF_POOL (1) -> false, true, true
qry="select count(subnet_id) from dhcp6_subnet where reservations_global = false and reservations_in_subnet = true and reservations_out_of_pool = true and subnet_prefix = '2001:db8:1::/64'"
run_statement "#6_subnet_out_of_pool" "$qry" 1
# Test GLOBAL (2) -> 4
qry="select count(subnet_id) from dhcp6_subnet where reservation_mode = 4 and subnet_prefix = '2001:db8:2::/64'"
# Test GLOBAL (2) -> true, false, false
qry="select count(subnet_id) from dhcp6_subnet where reservations_global = true and reservations_in_subnet = false and reservations_out_of_pool = false and subnet_prefix = '2001:db8:2::/64'"
run_statement "#6_subnet_global" "$qry" 1
# Test ALL (3) -> 2
qry="select count(subnet_id) from dhcp6_subnet where reservation_mode = 2 and subnet_prefix = '2001:db8:3::/64'"
# Test ALL (3) -> false, true, false
qry="select count(subnet_id) from dhcp6_subnet where reservations_global = false and reservations_in_subnet = true and reservations_out_of_pool = false and subnet_prefix = '2001:db8:3::/64'"
run_statement "#6_subnet_all" "$qry" 1
qry="select count(*) from dhcp4_shared_network;"

View File

@ -948,39 +948,6 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
}
}
\"reservations-out-of-pool\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_RESERVATIONS_OUT_OF_POOL(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("reservations-out-of-pool", driver.loc_);
}
}
\"reservations-in-subnet\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_RESERVATIONS_IN_SUBNET(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("reservations-in-subnet", driver.loc_);
}
}
\"reservations-global\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_RESERVATIONS_GLOBAL(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("reservations-global", driver.loc_);
}
}
\"reservation-mode\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
@ -1037,6 +1004,39 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
}
}
\"reservations-global\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_RESERVATIONS_GLOBAL(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("reservations-global", driver.loc_);
}
}
\"reservations-in-subnet\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_RESERVATIONS_IN_SUBNET(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("reservations-in-subnet", driver.loc_);
}
}
\"reservations-out-of-pool\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::DHCP4:
case isc::dhcp::Parser4Context::SUBNET4:
case isc::dhcp::Parser4Context::SHARED_NETWORK:
return isc::dhcp::Dhcp4Parser::make_RESERVATIONS_OUT_OF_POOL(driver.loc_);
default:
return isc::dhcp::Dhcp4Parser::make_STRING("reservations-out-of-pool", driver.loc_);
}
}
\"code\" {
switch(driver.ctx_) {
case isc::dhcp::Parser4Context::OPTION_DEF:

View File

@ -152,13 +152,13 @@ using namespace std;
INTERFACE "interface"
ID "id"
RESERVATION_MODE "reservation-mode"
RESERVATIONS_OUT_OF_POOL "reservations-out-of-pool"
RESERVATIONS_IN_SUBNET "reservations-in-subnet"
RESERVATIONS_GLOBAL "reservations-global"
DISABLED "disabled"
OUT_OF_POOL "out-of-pool"
GLOBAL "global"
ALL "all"
RESERVATIONS_GLOBAL "reservations-global"
RESERVATIONS_IN_SUBNET "reservations-in-subnet"
RESERVATIONS_OUT_OF_POOL "reservations-out-of-pool"
HOST_RESERVATION_IDENTIFIERS "host-reservation-identifiers"
@ -486,9 +486,9 @@ global_param: valid_lifetime
| config_control
| server_tag
| reservation_mode
| reservations_out_of_pool
| reservations_in_subnet
| reservations_global
| reservations_in_subnet
| reservations_out_of_pool
| calculate_tee_times
| t1_percent
| t2_percent
@ -1374,9 +1374,9 @@ subnet4_param: valid_lifetime
| require_client_classes
| reservations
| reservation_mode
| reservations_out_of_pool
| reservations_in_subnet
| reservations_global
| reservations_in_subnet
| reservations_out_of_pool
| relay
| match_client_id
| authoritative
@ -1472,10 +1472,10 @@ require_client_classes: REQUIRE_CLIENT_CLASSES {
ctx.leave();
};
reservations_out_of_pool: RESERVATIONS_OUT_OF_POOL COLON BOOLEAN {
ctx.unique("reservations-out-of-pool", ctx.loc2pos(@1));
reservations_global: RESERVATIONS_GLOBAL COLON BOOLEAN {
ctx.unique("reservations-global", ctx.loc2pos(@1));
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("reservations-out-of-pool", b);
ctx.stack_.back()->set("reservations-global", b);
};
reservations_in_subnet: RESERVATIONS_IN_SUBNET COLON BOOLEAN {
@ -1484,10 +1484,10 @@ reservations_in_subnet: RESERVATIONS_IN_SUBNET COLON BOOLEAN {
ctx.stack_.back()->set("reservations-in-subnet", b);
};
reservations_global: RESERVATIONS_GLOBAL COLON BOOLEAN {
ctx.unique("reservations-global", ctx.loc2pos(@1));
reservations_out_of_pool: RESERVATIONS_OUT_OF_POOL COLON BOOLEAN {
ctx.unique("reservations-out-of-pool", ctx.loc2pos(@1));
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("reservations-global", b);
ctx.stack_.back()->set("reservations-out-of-pool", b);
};
reservation_mode: RESERVATION_MODE {
@ -1558,9 +1558,9 @@ shared_network_param: name
| boot_file_name
| relay
| reservation_mode
| reservations_out_of_pool
| reservations_in_subnet
| reservations_global
| reservations_in_subnet
| reservations_out_of_pool
| client_class
| require_client_classes
| valid_lifetime

View File

@ -180,7 +180,9 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine,
}
// Find static reservations if not disabled for our subnet.
if (subnet->getHostReservationMode() != Network::HR_DISABLED) {
if (subnet->getReservationsGlobal() ||
subnet->getReservationsInSubnet() ||
subnet->getReservationsOutOfPool()) {
// Before we can check for static reservations, we need to prepare a set
// of identifiers to be used for this.
setHostIdentifiers();
@ -493,8 +495,11 @@ Dhcpv4Exchange::conditionallySetReservedClientClasses() {
if (context_->subnet_) {
SharedNetwork4Ptr shared_network;
context_->subnet_->getSharedNetwork(shared_network);
if (shared_network && !context_->globalHost()) {
setReservedClientClasses(context_);
if (shared_network) {
ConstHostPtr host = context_->currentHost();
if (host && (host->getIPv4SubnetID() != SUBNET_ID_GLOBAL)) {
setReservedClientClasses(context_);
}
}
}
}

View File

@ -367,53 +367,17 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
// default values and will insert derived values as well.
mutable_cfg = boost::const_pointer_cast<Element>(config_set);
bool found = false;
ConstElementPtr reservations_out_of_pool = mutable_cfg->get("reservations-out-of-pool");
ConstElementPtr reservations_in_subnet = mutable_cfg->get("reservations-in-subnet");
ConstElementPtr reservations_global = mutable_cfg->get("reservations-global");
if (reservations_out_of_pool || reservations_in_subnet || reservations_global) {
found = true;
}
ConstElementPtr reservation_mode = mutable_cfg->get("reservation-mode");
if (reservation_mode) {
LOG_WARN(dhcp4_logger, DHCP4_DEPRECATED_RESERVATION_MODE);
if (found) {
isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
" and one of 'reservations-out-of-pool'"
" , 'reservations-in-subnet' or"
" 'reservations-global' parameters");
}
}
// reset all other reservation flags to overwrite default values.
if (found) {
bool force_true = false;
if (!reservations_out_of_pool) {
mutable_cfg->set("reservations-out-of-pool", Element::create(false));
} else {
force_true = reservations_out_of_pool->boolValue();
}
if (!reservations_in_subnet) {
if (force_true) {
mutable_cfg->set("reservations-in-subnet", Element::create(true));
} else {
mutable_cfg->set("reservations-in-subnet", Element::create(false));
}
} else if (force_true && !reservations_in_subnet->boolValue()) {
isc_throw(DhcpConfigError, "invalid use of disabled 'reservations-in-subnet'"
" when enabled 'reservations-out-of-pool'");
}
if (!reservations_global) {
mutable_cfg->set("reservations-global", Element::create(false));
}
}
// Relocate dhcp-ddns parameters that have moved to global scope.
// Rule is that a global value overrides the dhcp-ddns value, so
// we need to do this before we apply global defaults.
// Note this is done for backward compatibility.
srv_cfg->moveDdnsParams(mutable_cfg);
// Move from reservation mode to new reservations flags.
if (BaseNetworkParser::moveReservationMode(mutable_cfg)) {
LOG_WARN(dhcp4_logger, DHCP4_DEPRECATED_RESERVATION_MODE);
}
// Set all default values if not specified by the user.
SimpleParser4::setAllDefaults(mutable_cfg);
@ -432,14 +396,6 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
// Apply global options in the staging config, e.g. ip-reservations-unique
global_parser.parseEarly(srv_cfg, mutable_cfg);
// If using deprecated reservation-mode, remove defaults for new parameters
// reservations-out-of-pool, reservations-in-subnet and reservations-global.
if (reservation_mode) {
mutable_cfg->remove("reservations-out-of-pool");
mutable_cfg->remove("reservations-in-subnet");
mutable_cfg->remove("reservations-global");
}
// We need definitions first
ConstElementPtr option_defs = mutable_cfg->get("option-def");
if (option_defs) {
@ -678,9 +634,9 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
(config_pair.first == "boot-file-name") ||
(config_pair.first == "server-tag") ||
(config_pair.first == "reservation-mode") ||
(config_pair.first == "reservations-out-of-pool") ||
(config_pair.first == "reservations-in-subnet") ||
(config_pair.first == "reservations-global") ||
(config_pair.first == "reservations-in-subnet") ||
(config_pair.first == "reservations-out-of-pool") ||
(config_pair.first == "calculate-tee-times") ||
(config_pair.first == "t1-percent") ||
(config_pair.first == "t2-percent") ||

View File

@ -5280,96 +5280,10 @@ TEST_F(Dhcp4ParserTest, reservationBogus) {
checkResult(x, 1);
}
/// The goal of this test is to verify that Host Reservation modes can be
/// The goal of this test is to verify that Host Reservation flags can be
/// specified on a per-subnet basis.
TEST_F(Dhcp4ParserTest, hostReservationPerSubnet) {
/// - Configuration:
/// - only addresses (no prefixes)
/// - 5 subnets with:
/// - 192.0.1.0/24 (all reservations enabled)
/// - 192.0.2.0/24 (out-of-pool reservations)
/// - 192.0.3.0/24 (reservations disabled)
/// - 192.0.4.0/24 (global reservations)
/// - 192.0.5.0/24 (reservations not specified)
const char* hr_config =
"{ "
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet4\": [ { "
" \"pools\": [ { \"pool\": \"192.0.1.0/24\" } ],"
" \"subnet\": \"192.0.1.0/24\", "
" \"reservation-mode\": \"all\""
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.2.0/24\" } ],"
" \"subnet\": \"192.0.2.0/24\", "
" \"reservation-mode\": \"out-of-pool\""
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.3.0/24\" } ],"
" \"subnet\": \"192.0.3.0/24\", "
" \"reservation-mode\": \"disabled\""
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.4.0/24\" } ],"
" \"subnet\": \"192.0.4.0/24\", "
" \"reservation-mode\": \"global\""
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.5.0/24\" } ],"
" \"subnet\": \"192.0.5.0/24\""
" } ],"
"\"valid-lifetime\": 4000 }";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP4(hr_config));
extractConfig(hr_config);
ConstElementPtr result;
EXPECT_NO_THROW(result = configureDhcp4Server(*srv_, json));
// returned value should be 0 (success)
checkResult(result, 0);
// Let's get all subnets and check that there are 5 of them.
ConstCfgSubnets4Ptr subnets = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
ASSERT_TRUE(subnets);
const Subnet4Collection* subnet_col = subnets->getAll();
ASSERT_EQ(5, subnet_col->size()); // We expect 5 subnets
// Let's check if the parsed subnets have correct HR modes.
// Subnet 1
Subnet4Ptr subnet;
subnet = subnets->selectSubnet(IOAddress("192.0.1.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
// Subnet 2
subnet = subnets->selectSubnet(IOAddress("192.0.2.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
// Subnet 3
subnet = subnets->selectSubnet(IOAddress("192.0.3.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_DISABLED, subnet->getHostReservationMode());
// Subnet 4
subnet = subnets->selectSubnet(IOAddress("192.0.4.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_GLOBAL, subnet->getHostReservationMode());
// Subnet 5
subnet = subnets->selectSubnet(IOAddress("192.0.5.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
}
/// The goal of this test is to verify that Host Reservation modes can be
/// specified on a per-subnet basis.
TEST_F(Dhcp4ParserTest, hostReservationModesPerSubnet) {
/// - Configuration:
/// - only addresses (no prefixes)
/// - 7 subnets with:
@ -5387,24 +5301,30 @@ TEST_F(Dhcp4ParserTest, hostReservationModesPerSubnet) {
"\"subnet4\": [ { "
" \"pools\": [ { \"pool\": \"192.0.1.0/24\" } ],"
" \"subnet\": \"192.0.1.0/24\", "
" \"reservations-in-subnet\": true"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": false"
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.2.0/24\" } ],"
" \"subnet\": \"192.0.2.0/24\", "
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": true"
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.3.0/24\" } ],"
" \"subnet\": \"192.0.3.0/24\", "
" \"reservations-out-of-pool\": false,"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": false,"
" \"reservations-global\": false"
" \"reservations-out-of-pool\": false"
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.4.0/24\" } ],"
" \"subnet\": \"192.0.4.0/24\", "
" \"reservations-global\": true"
" \"reservations-global\": true,"
" \"reservations-in-subnet\": false,"
" \"reservations-out-of-pool\": false"
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.5.0/24\" } ],"
@ -5413,16 +5333,16 @@ TEST_F(Dhcp4ParserTest, hostReservationModesPerSubnet) {
" {"
" \"pools\": [ { \"pool\": \"192.0.6.0/24\" } ],"
" \"subnet\": \"192.0.6.0/24\", "
" \"reservations-out-of-pool\": false,"
" \"reservations-global\": true,"
" \"reservations-in-subnet\": true,"
" \"reservations-global\": true"
" \"reservations-out-of-pool\": false"
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.7.0/24\" } ],"
" \"subnet\": \"192.0.7.0/24\", "
" \"reservations-out-of-pool\": true,"
" \"reservations-global\": true,"
" \"reservations-in-subnet\": true,"
" \"reservations-global\": true"
" \"reservations-out-of-pool\": true"
" } ],"
"\"valid-lifetime\": 4000 }";
@ -5447,41 +5367,54 @@ TEST_F(Dhcp4ParserTest, hostReservationModesPerSubnet) {
Subnet4Ptr subnet;
subnet = subnets->selectSubnet(IOAddress("192.0.1.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 2
subnet = subnets->selectSubnet(IOAddress("192.0.2.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_TRUE(subnet->getReservationsOutOfPool());
// Subnet 3
subnet = subnets->selectSubnet(IOAddress("192.0.3.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_DISABLED, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_FALSE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 4
subnet = subnets->selectSubnet(IOAddress("192.0.4.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_GLOBAL, subnet->getHostReservationMode());
EXPECT_TRUE(subnet->getReservationsGlobal());
EXPECT_FALSE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 5
subnet = subnets->selectSubnet(IOAddress("192.0.5.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 6
subnet = subnets->selectSubnet(IOAddress("192.0.6.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL|Network::HR_GLOBAL, subnet->getHostReservationMode());
EXPECT_TRUE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 7
subnet = subnets->selectSubnet(IOAddress("192.0.7.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_OUT_OF_POOL|Network::HR_GLOBAL,
subnet->getHostReservationMode());
EXPECT_TRUE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_TRUE(subnet->getReservationsOutOfPool());
}
/// The goal of this test is to verify that Host Reservation modes can be
/// The goal of this test is to verify that Host Reservation flags can be
/// specified globally.
TEST_F(Dhcp4ParserTest, hostReservationGlobal) {
@ -5494,73 +5427,15 @@ TEST_F(Dhcp4ParserTest, hostReservationGlobal) {
"{ "
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"reservation-mode\": \"out-of-pool\", "
"\"subnet4\": [ { "
" \"pools\": [ { \"pool\": \"192.0.2.0/24\" } ],"
" \"subnet\": \"192.0.2.0/24\", "
" \"reservation-mode\": \"all\""
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.3.0/24\" } ],"
" \"subnet\": \"192.0.3.0/24\""
" } ],"
"\"valid-lifetime\": 4000 }";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP4(hr_config));
extractConfig(hr_config);
ConstElementPtr result;
EXPECT_NO_THROW(result = configureDhcp4Server(*srv_, json));
// returned value should be 0 (success)
checkResult(result, 0);
// Let's get all subnets and check that there are 4 of them.
ConstCfgSubnets4Ptr subnets = CfgMgr::instance().getStagingCfg()->getCfgSubnets4();
ASSERT_TRUE(subnets);
const Subnet4Collection* subnet_col = subnets->getAll();
ASSERT_EQ(2, subnet_col->size()); // We expect 2 subnets
// Let's check if the parsed subnets have correct HR modes.
// Subnet 1
Subnet4Ptr subnet;
subnet = subnets->selectSubnet(IOAddress("192.0.2.1"));
ASSERT_TRUE(subnet);
// Reset the fetch global function to staging (vs current) config.
subnet->setFetchGlobalsFn([]() -> ConstElementPtr {
return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
});
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
// Subnet 2
subnet = subnets->selectSubnet(IOAddress("192.0.3.1"));
ASSERT_TRUE(subnet);
// Reset the fetch global function to staging (vs current) config.
subnet->setFetchGlobalsFn([]() -> ConstElementPtr {
return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
});
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
}
/// The goal of this test is to verify that Host Reservation modes can be
/// specified globally.
TEST_F(Dhcp4ParserTest, hostReservationModesGlobal) {
/// - Configuration:
/// - only addresses (no prefixes)
/// - 2 subnets with :
/// - 192.0.2.0/24 (all reservations enabled)
/// - 192.0.3.0/24 (reservations not specified)
const char* hr_config =
"{ "
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"reservations-global\": false,"
"\"reservations-in-subnet\": true,"
"\"reservations-out-of-pool\": true,"
"\"subnet4\": [ { "
" \"pools\": [ { \"pool\": \"192.0.2.0/24\" } ],"
" \"subnet\": \"192.0.2.0/24\", "
" \"reservations-in-subnet\": true"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": false"
" },"
" {"
" \"pools\": [ { \"pool\": \"192.0.3.0/24\" } ],"
@ -5593,7 +5468,9 @@ TEST_F(Dhcp4ParserTest, hostReservationModesGlobal) {
subnet->setFetchGlobalsFn([]() -> ConstElementPtr {
return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
});
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 2
subnet = subnets->selectSubnet(IOAddress("192.0.3.1"));
@ -5602,7 +5479,9 @@ TEST_F(Dhcp4ParserTest, hostReservationModesGlobal) {
subnet->setFetchGlobalsFn([]() -> ConstElementPtr {
return (CfgMgr::instance().getStagingCfg()->getConfiguredGlobals());
});
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_TRUE(subnet->getReservationsOutOfPool());
}
/// Check that the decline-probation-period has a default value when not
@ -6459,7 +6338,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
" \"relay\": {\n"
" \"ip-address\": \"5.6.7.8\"\n"
" },\n"
" \"reservations-out-of-pool\": true,"
" \"reservations-global\": false,\n"
" \"reservations-in-subnet\": true,\n"
" \"reservations-out-of-pool\": true,\n"
" \"renew-timer\": 10,\n"
" \"rebind-timer\": 20,\n"
" \"valid-lifetime\": 40,\n"
@ -6485,7 +6366,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
" \"relay\": {\n"
" \"ip-address\": \"55.66.77.88\"\n"
" },\n"
" \"reservations-global\": false"
" \"reservations-global\": false,\n"
" \"reservations-in-subnet\": false,\n"
" \"reservations-out-of-pool\": false\n"
" }\n"
" ]\n"
" },\n"
@ -6536,7 +6419,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
EXPECT_EQ("foo", s->getSname().get());
EXPECT_EQ("bar", s->getFilename().get());
EXPECT_TRUE(s->hasRelayAddress(IOAddress("5.6.7.8")));
EXPECT_EQ(Network::HR_OUT_OF_POOL, s->getHostReservationMode());
EXPECT_FALSE(s->getReservationsGlobal());
EXPECT_TRUE(s->getReservationsInSubnet());
EXPECT_TRUE(s->getReservationsOutOfPool());
// For the second subnet, the renew-timer should be 100, because it
// was specified explicitly. Other parameters a derived
@ -6553,7 +6438,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
EXPECT_EQ("some-name.example.org", s->getSname().get());
EXPECT_EQ("bootfile.efi", s->getFilename().get());
EXPECT_TRUE(s->hasRelayAddress(IOAddress("55.66.77.88")));
EXPECT_EQ(Network::HR_DISABLED, s->getHostReservationMode());
EXPECT_FALSE(s->getReservationsGlobal());
EXPECT_FALSE(s->getReservationsInSubnet());
EXPECT_FALSE(s->getReservationsOutOfPool());
// Ok, now check the second shared subnet.
net = nets->at(1);
@ -6574,7 +6461,9 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
EXPECT_TRUE(s->getSname().empty());
EXPECT_TRUE(s->getFilename().empty());
EXPECT_FALSE(s->hasRelays());
EXPECT_EQ(Network::HR_ALL, s->getHostReservationMode());
EXPECT_FALSE(s->getReservationsGlobal());
EXPECT_TRUE(s->getReservationsInSubnet());
EXPECT_FALSE(s->getReservationsOutOfPool());
}
// This test checks if client-class is derived properly.

View File

@ -1809,7 +1809,7 @@ TEST_F(DORATest, reservationModeDisabled) {
// Set explicit HW address so as it matches the reservation in the
// configuration used below.
client.setHWAddress("aa:bb:cc:dd:ee:ff");
// Configure DHCP server. In this configuration the reservation flags are
// Configure DHCP server. In this configuration the reservations flags are
// set to false. Thus, the server should ignore the reservation for
// this client.
configure(DORA_CONFIGS[13], *client.getServer());

View File

@ -1258,39 +1258,6 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
}
}
\"reservations-out-of-pool\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_RESERVATIONS_OUT_OF_POOL(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("reservations-out-of-pool", driver.loc_);
}
}
\"reservations-in-subnet\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_RESERVATIONS_IN_SUBNET(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("reservations-in-subnet", driver.loc_);
}
}
\"reservations-global\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_RESERVATIONS_GLOBAL(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("reservations-global", driver.loc_);
}
}
\"reservation-mode\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
@ -1347,6 +1314,39 @@ ControlCharacterFill [^"\\]|\\["\\/bfnrtu]
}
}
\"reservations-global\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_RESERVATIONS_GLOBAL(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("reservations-global", driver.loc_);
}
}
\"reservations-in-subnet\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_RESERVATIONS_IN_SUBNET(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("reservations-in-subnet", driver.loc_);
}
}
\"reservations-out-of-pool\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::DHCP6:
case isc::dhcp::Parser6Context::SUBNET6:
case isc::dhcp::Parser6Context::SHARED_NETWORK:
return isc::dhcp::Dhcp6Parser::make_RESERVATIONS_OUT_OF_POOL(driver.loc_);
default:
return isc::dhcp::Dhcp6Parser::make_STRING("reservations-out-of-pool", driver.loc_);
}
}
\"code\" {
switch(driver.ctx_) {
case isc::dhcp::Parser6Context::OPTION_DEF:

View File

@ -145,13 +145,13 @@ using namespace std;
ID "id"
RAPID_COMMIT "rapid-commit"
RESERVATION_MODE "reservation-mode"
RESERVATIONS_OUT_OF_POOL "reservations-out-of-pool"
RESERVATIONS_IN_SUBNET "reservations-in-subnet"
RESERVATIONS_GLOBAL "reservations-global"
DISABLED "disabled"
OUT_OF_POOL "out-of-pool"
GLOBAL "global"
ALL "all"
RESERVATIONS_GLOBAL "reservations-global"
RESERVATIONS_IN_SUBNET "reservations-in-subnet"
RESERVATIONS_OUT_OF_POOL "reservations-out-of-pool"
MAC_SOURCES "mac-sources"
RELAY_SUPPLIED_OPTIONS "relay-supplied-options"
@ -495,9 +495,9 @@ global_param: data_directory
| config_control
| server_tag
| reservation_mode
| reservations_out_of_pool
| reservations_in_subnet
| reservations_global
| reservations_in_subnet
| reservations_out_of_pool
| calculate_tee_times
| t1_percent
| t2_percent
@ -1393,9 +1393,9 @@ subnet6_param: preferred_lifetime
| require_client_classes
| reservations
| reservation_mode
| reservations_out_of_pool
| reservations_in_subnet
| reservations_global
| reservations_in_subnet
| reservations_out_of_pool
| relay
| user_context
| comment
@ -1465,10 +1465,10 @@ require_client_classes: REQUIRE_CLIENT_CLASSES {
ctx.leave();
};
reservations_out_of_pool: RESERVATIONS_OUT_OF_POOL COLON BOOLEAN {
ctx.unique("reservations-out-of-pool", ctx.loc2pos(@1));
reservations_global: RESERVATIONS_GLOBAL COLON BOOLEAN {
ctx.unique("reservations-global", ctx.loc2pos(@1));
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("reservations-out-of-pool", b);
ctx.stack_.back()->set("reservations-global", b);
};
reservations_in_subnet: RESERVATIONS_IN_SUBNET COLON BOOLEAN {
@ -1477,10 +1477,10 @@ reservations_in_subnet: RESERVATIONS_IN_SUBNET COLON BOOLEAN {
ctx.stack_.back()->set("reservations-in-subnet", b);
};
reservations_global: RESERVATIONS_GLOBAL COLON BOOLEAN {
ctx.unique("reservations-global", ctx.loc2pos(@1));
reservations_out_of_pool: RESERVATIONS_OUT_OF_POOL COLON BOOLEAN {
ctx.unique("reservations-out-of-pool", ctx.loc2pos(@1));
ElementPtr b(new BoolElement($3, ctx.loc2pos(@3)));
ctx.stack_.back()->set("reservations-global", b);
ctx.stack_.back()->set("reservations-out-of-pool", b);
};
reservation_mode: RESERVATION_MODE {
@ -1553,9 +1553,9 @@ shared_network_param: name
| option_data_list
| relay
| reservation_mode
| reservations_out_of_pool
| reservations_in_subnet
| reservations_global
| reservations_in_subnet
| reservations_out_of_pool
| client_class
| require_client_classes
| preferred_lifetime

View File

@ -3774,8 +3774,11 @@ Dhcpv6Srv::conditionallySetReservedClientClasses(const Pkt6Ptr& pkt,
if (ctx.subnet_) {
SharedNetwork6Ptr shared_network;
ctx.subnet_->getSharedNetwork(shared_network);
if (shared_network && !ctx.globalHost()) {
setReservedClientClasses(pkt, ctx);
if (shared_network) {
ConstHostPtr host = ctx.currentHost();
if (host && (host->getIPv6SubnetID() != SUBNET_ID_GLOBAL)) {
setReservedClientClasses(pkt, ctx);
}
}
}
}

View File

@ -450,7 +450,12 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
// Print the list of known backends.
HostDataSourceFactory::printRegistered();
// Answer will hold the result.
// This is a way to convert ConstElementPtr to ElementPtr.
// We need a config that can be edited, because we will insert
// default values and will insert derived values as well.
ElementPtr mutable_cfg = boost::const_pointer_cast<Element>(config_set);
// answer will hold the result.
ConstElementPtr answer;
// Rollback informs whether error occurred and original data
// have to be restored to global storages.
@ -468,53 +473,17 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
// default values and will insert derived values as well.
mutable_cfg = boost::const_pointer_cast<Element>(config_set);
bool found = false;
ConstElementPtr reservations_out_of_pool = mutable_cfg->get("reservations-out-of-pool");
ConstElementPtr reservations_in_subnet = mutable_cfg->get("reservations-in-subnet");
ConstElementPtr reservations_global = mutable_cfg->get("reservations-global");
if (reservations_out_of_pool || reservations_in_subnet || reservations_global) {
found = true;
}
ConstElementPtr reservation_mode = mutable_cfg->get("reservation-mode");
if (reservation_mode) {
LOG_WARN(dhcp6_logger, DHCP6_DEPRECATED_RESERVATION_MODE);
if (found) {
isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
" and one of 'reservations-out-of-pool'"
" , 'reservations-in-subnet' or"
" 'reservations-global' parameters");
}
}
// reset all other reservation flags to overwrite default values.
if (found) {
bool force_true = false;
if (!reservations_out_of_pool) {
mutable_cfg->set("reservations-out-of-pool", Element::create(false));
} else {
force_true = reservations_out_of_pool->boolValue();
}
if (!reservations_in_subnet) {
if (force_true) {
mutable_cfg->set("reservations-in-subnet", Element::create(true));
} else {
mutable_cfg->set("reservations-in-subnet", Element::create(false));
}
} else if (force_true && !reservations_in_subnet->boolValue()) {
isc_throw(DhcpConfigError, "invalid use of disabled 'reservations-in-subnet'"
" when enabled 'reservations-out-of-pool'");
}
if (!reservations_global) {
mutable_cfg->set("reservations-global", Element::create(false));
}
}
// Relocate dhcp-ddns parameters that have moved to global scope.
// Rule is that a global value overrides the dhcp-ddns value, so
// we need to do this before we apply global defaults.
// Note this is done for backward compatibility.
srv_config->moveDdnsParams(mutable_cfg);
// Move from reservation mode to new reservations flags.
if (BaseNetworkParser::moveReservationMode(mutable_cfg)) {
LOG_WARN(dhcp6_logger, DHCP6_DEPRECATED_RESERVATION_MODE);
}
// Set all default values if not specified by the user.
SimpleParser6::setAllDefaults(mutable_cfg);
@ -533,14 +502,6 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
// Apply global options in the staging config, e.g. ip-reservations-unique
global_parser.parseEarly(srv_config, mutable_cfg);
// If using deprecated reservation-mode, remove defaults for new parameters
// reservations-out-of-pool, reservations-in-subnet and reservations-global.
if (reservation_mode) {
mutable_cfg->remove("reservations-out-of-pool");
mutable_cfg->remove("reservations-in-subnet");
mutable_cfg->remove("reservations-global");
}
// Specific check for this global parameter.
ConstElementPtr data_directory = mutable_cfg->get("data-directory");
if (data_directory) {
@ -810,9 +771,9 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
(config_pair.first == "dhcp4o6-port") ||
(config_pair.first == "server-tag") ||
(config_pair.first == "reservation-mode") ||
(config_pair.first == "reservations-out-of-pool") ||
(config_pair.first == "reservations-in-subnet") ||
(config_pair.first == "reservations-global") ||
(config_pair.first == "reservations-in-subnet") ||
(config_pair.first == "reservations-out-of-pool") ||
(config_pair.first == "calculate-tee-times") ||
(config_pair.first == "t1-percent") ||
(config_pair.first == "t2-percent") ||

View File

@ -5649,99 +5649,10 @@ TEST_F(Dhcp6ParserTest, macSourcesBogus) {
checkResult(status, 1);
}
/// The goal of this test is to verify that Host Reservation modes can be
/// The goal of this test is to verify that Host Reservation flags can be
/// specified on a per-subnet basis.
TEST_F(Dhcp6ParserTest, hostReservationPerSubnet) {
/// - Configuration:
/// - only addresses (no prefixes)
/// - 5 subnets with:
/// - 2001:db8:1::/64 (all reservations enabled)
/// - 2001:db8:2::/64 (out-of-pool reservations)
/// - 2001:db8:3::/64 (reservations disabled)
/// - 2001:db8:4::/64 (global reservations)
/// - 2001:db8:5::/64 (reservations not specified)
const char* hr_config =
"{"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
" \"subnet\": \"2001:db8:1::/48\", "
" \"reservation-mode\": \"all\""
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ],"
" \"subnet\": \"2001:db8:2::/48\", "
" \"reservation-mode\": \"out-of-pool\""
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:3::/64\" } ],"
" \"subnet\": \"2001:db8:3::/48\", "
" \"reservation-mode\": \"disabled\""
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:4::/64\" } ],"
" \"subnet\": \"2001:db8:4::/48\", "
" \"reservation-mode\": \"global\""
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:5::/64\" } ],"
" \"subnet\": \"2001:db8:5::/48\" "
" } ],"
"\"valid-lifetime\": 4000 }";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP6(hr_config));
extractConfig(hr_config);
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
// returned value should be 0 (success)
checkResult(status, 0);
CfgMgr::instance().commit();
// Let's get all subnets and check that there are 5 of them.
ConstCfgSubnets6Ptr subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6();
ASSERT_TRUE(subnets);
const Subnet6Collection* subnet_col = subnets->getAll();
ASSERT_EQ(5, subnet_col->size()); // We expect 5 subnets
// Let's check if the parsed subnets have correct HR modes.
// Subnet 1
Subnet6Ptr subnet;
subnet = subnets->selectSubnet(IOAddress("2001:db8:1::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
// Subnet 2
subnet = subnets->selectSubnet(IOAddress("2001:db8:2::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
// Subnet 3
subnet = subnets->selectSubnet(IOAddress("2001:db8:3::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_DISABLED, subnet->getHostReservationMode());
// Subnet 4
subnet = subnets->selectSubnet(IOAddress("2001:db8:4::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_GLOBAL, subnet->getHostReservationMode());
// Subnet 5
subnet = subnets->selectSubnet(IOAddress("2001:db8:5::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
}
/// The goal of this test is to verify that Host Reservation modes can be
/// specified on a per-subnet basis.
TEST_F(Dhcp6ParserTest, hostReservationModesPerSubnet) {
/// - Configuration:
/// - only addresses (no prefixes)
/// - 7 subnets with:
@ -5760,24 +5671,30 @@ TEST_F(Dhcp6ParserTest, hostReservationModesPerSubnet) {
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
" \"subnet\": \"2001:db8:1::/48\", "
" \"reservations-in-subnet\": true"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": false"
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ],"
" \"subnet\": \"2001:db8:2::/48\", "
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": true"
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:3::/64\" } ],"
" \"subnet\": \"2001:db8:3::/48\", "
" \"reservations-out-of-pool\": false,"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": false,"
" \"reservations-global\": false"
" \"reservations-out-of-pool\": false"
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:4::/64\" } ],"
" \"subnet\": \"2001:db8:4::/48\", "
" \"reservations-global\": true"
" \"reservations-global\": true,"
" \"reservations-in-subnet\": false,"
" \"reservations-out-of-pool\": false"
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:5::/64\" } ],"
@ -5786,16 +5703,16 @@ TEST_F(Dhcp6ParserTest, hostReservationModesPerSubnet) {
" {"
" \"pools\": [ { \"pool\": \"2001:db8:6::/64\" } ],"
" \"subnet\": \"2001:db8:6::/48\", "
" \"reservations-out-of-pool\": false,"
" \"reservations-global\": true,"
" \"reservations-in-subnet\": true,"
" \"reservations-global\": true"
" \"reservations-out-of-pool\": false"
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:7::/64\" } ],"
" \"subnet\": \"2001:db8:7::/48\", "
" \"reservations-out-of-pool\": true,"
" \"reservations-global\": true,"
" \"reservations-in-subnet\": true,"
" \"reservations-global\": true"
" \"reservations-out-of-pool\": true"
" } ],"
"\"valid-lifetime\": 4000 }";
@ -5822,41 +5739,55 @@ TEST_F(Dhcp6ParserTest, hostReservationModesPerSubnet) {
Subnet6Ptr subnet;
subnet = subnets->selectSubnet(IOAddress("2001:db8:1::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 2
subnet = subnets->selectSubnet(IOAddress("2001:db8:2::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_TRUE(subnet->getReservationsOutOfPool());
// Subnet 3
subnet = subnets->selectSubnet(IOAddress("2001:db8:3::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_DISABLED, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_FALSE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 4
subnet = subnets->selectSubnet(IOAddress("2001:db8:4::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_GLOBAL, subnet->getHostReservationMode());
EXPECT_TRUE(subnet->getReservationsGlobal());
EXPECT_FALSE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 5
subnet = subnets->selectSubnet(IOAddress("2001:db8:5::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 6
subnet = subnets->selectSubnet(IOAddress("2001:db8:6::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL|Network::HR_GLOBAL, subnet->getHostReservationMode());
EXPECT_TRUE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 7
subnet = subnets->selectSubnet(IOAddress("2001:db8:7::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_OUT_OF_POOL|Network::HR_GLOBAL,
subnet->getHostReservationMode());
EXPECT_TRUE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_TRUE(subnet->getReservationsOutOfPool());
}
/// The goal of this test is to verify that Host Reservation modes can be
/// The goal of this test is to verify that Host Reservation flags can be
/// specified globally.
TEST_F(Dhcp6ParserTest, hostReservationGlobal) {
@ -5870,68 +5801,15 @@ TEST_F(Dhcp6ParserTest, hostReservationGlobal) {
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"reservation-mode\": \"out-of-pool\", "
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
" \"subnet\": \"2001:db8:1::/48\", "
" \"reservation-mode\": \"all\""
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ],"
" \"subnet\": \"2001:db8:2::/48\" "
" } ],"
"\"valid-lifetime\": 4000 }";
ConstElementPtr json;
ASSERT_NO_THROW(json = parseDHCP6(hr_config));
extractConfig(hr_config);
ConstElementPtr status;
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
// returned value should be 0 (success)
checkResult(status, 0);
CfgMgr::instance().commit();
// Let's get all subnets and check that there are 2 of them.
ConstCfgSubnets6Ptr subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6();
ASSERT_TRUE(subnets);
const Subnet6Collection* subnet_col = subnets->getAll();
ASSERT_EQ(2, subnet_col->size()); // We expect 2 subnets
// Let's check if the parsed subnets have correct HR modes.
// Subnet 1
Subnet6Ptr subnet;
subnet = subnets->selectSubnet(IOAddress("2001:db8:1::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
// Subnet 2
subnet = subnets->selectSubnet(IOAddress("2001:db8:2::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
}
/// The goal of this test is to verify that Host Reservation modes can be
/// specified globally.
TEST_F(Dhcp6ParserTest, hostReservationModesGlobal) {
/// - Configuration:
/// - only addresses (no prefixes)
/// - 2 subnets with:
/// - 2001:db8:1::/64 (all reservations enabled)
/// - 2001:db8:2::/64 (reservations not specified)
const char* hr_config =
"{"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"reservations-global\": false,"
"\"reservations-in-subnet\": true,"
"\"reservations-out-of-pool\": true,"
"\"subnet6\": [ { "
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
" \"subnet\": \"2001:db8:1::/48\", "
" \"reservations-in-subnet\": true"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": false"
" },"
" {"
" \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ],"
@ -5962,12 +5840,16 @@ TEST_F(Dhcp6ParserTest, hostReservationModesGlobal) {
Subnet6Ptr subnet;
subnet = subnets->selectSubnet(IOAddress("2001:db8:1::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_FALSE(subnet->getReservationsOutOfPool());
// Subnet 2
subnet = subnets->selectSubnet(IOAddress("2001:db8:2::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
EXPECT_FALSE(subnet->getReservationsGlobal());
EXPECT_TRUE(subnet->getReservationsInSubnet());
EXPECT_TRUE(subnet->getReservationsOutOfPool());
}
/// The goal of this test is to verify that configuration can include
@ -6889,7 +6771,9 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
" \"ip-address\": \"1111::1\"\n"
" },\n"
" \"rapid-commit\": true,\n"
" \"reservations-global\": false,"
" \"reservations-global\": false,\n"
" \"reservations-in-subnet\": false,\n"
" \"reservations-out-of-pool\": false,\n"
" \"subnet6\": [\n"
" { \n"
" \"subnet\": \"2001:db1::/48\",\n"
@ -6911,7 +6795,9 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
" \"max-valid-lifetime\": 500, \n"
" \"interface-id\": \"twotwo\",\n"
" \"rapid-commit\": true,\n"
" \"reservations-out-of-pool\": true"
" \"reservations-global\": false,\n"
" \"reservations-in-subnet\": true,\n"
" \"reservations-out-of-pool\": true\n"
" }\n"
" ]\n"
" },\n"
@ -6957,7 +6843,9 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
EXPECT_TRUE(iface_id1.equals(s->getInterfaceId()));
EXPECT_TRUE(s->hasRelayAddress(IOAddress("1111::1")));
EXPECT_TRUE(s->getRapidCommit());
EXPECT_EQ(Network::HR_DISABLED, s->getHostReservationMode());
EXPECT_FALSE(s->getReservationsGlobal());
EXPECT_FALSE(s->getReservationsInSubnet());
EXPECT_FALSE(s->getReservationsOutOfPool());
EXPECT_TRUE(s->getStoreExtendedInfo());
// For the second subnet, the renew-timer should be 100, because it
@ -6970,7 +6858,9 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
EXPECT_TRUE(iface_id2.equals(s->getInterfaceId()));
EXPECT_TRUE(s->hasRelayAddress(IOAddress("2222::2")));
EXPECT_TRUE(s->getRapidCommit());
EXPECT_EQ(Network::HR_OUT_OF_POOL, s->getHostReservationMode());
EXPECT_FALSE(s->getReservationsGlobal());
EXPECT_TRUE(s->getReservationsInSubnet());
EXPECT_TRUE(s->getReservationsOutOfPool());
EXPECT_TRUE(s->getStoreExtendedInfo());
// Ok, now check the second shared subnet.
@ -6986,7 +6876,9 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
EXPECT_FALSE(s->getInterfaceId());
EXPECT_FALSE(s->hasRelays());
EXPECT_FALSE(s->getRapidCommit());
EXPECT_EQ(Network::HR_ALL, s->getHostReservationMode());
EXPECT_FALSE(s->getReservationsGlobal());
EXPECT_TRUE(s->getReservationsInSubnet());
EXPECT_FALSE(s->getReservationsOutOfPool());
EXPECT_FALSE(s->getStoreExtendedInfo());
}

View File

@ -194,7 +194,9 @@ const char* CONFIGS[] = {
" \"pools\": [ { \"pool\": \"2001:db8:1::1 - 2001:db8:1::10\" } ],"
" \"subnet\": \"2001:db8:1::/48\", "
" \"interface\": \"eth0\", "
" \"reservation-mode\": \"out-of-pool\","
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": true,"
" \"reservations\": [ "
" {"
" \"duid\": \"aa:bb:cc:dd:ee:ff\","

View File

@ -267,7 +267,7 @@ public:
MySqlBinding::createString(RELAY_BUF_LENGTH), // relay
MySqlBinding::createInteger<uint32_t>(), // renew_timer
MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // require_client_classes
MySqlBinding::createInteger<uint8_t>(), // reservation_mode
MySqlBinding::createInteger<uint8_t>(), // reservations_global
MySqlBinding::createString(SERVER_HOSTNAME_BUF_LENGTH), // server_hostname
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // shared_network_name
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
@ -316,6 +316,8 @@ public:
MySqlBinding::createInteger<uint8_t>(), // ddns_replace_client_name
MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_generated_prefix
MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_qualifying_suffix
MySqlBinding::createInteger<uint8_t>(), // reservations_in_subnet
MySqlBinding::createInteger<uint8_t>(), // reservations_out_of_pool
MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
};
@ -353,13 +355,17 @@ public:
// subnet_id
SubnetID subnet_id(out_bindings[0]->getInteger<uint32_t>());
// subnet_prefix
std::string subnet_prefix = out_bindings[1]->getString();
auto prefix_pair = Subnet4::parsePrefix(subnet_prefix);
// renew_timer
auto renew_timer = createTriplet(out_bindings[13]);
// rebind_timer
auto rebind_timer = createTriplet(out_bindings[11]);
// valid_lifetime (and {min,max)_valid_lifetime)
auto valid_lifetime = createTriplet(out_bindings[19],
out_bindings[53],
@ -374,6 +380,7 @@ public:
if (!out_bindings[2]->amNull()) {
last_subnet->get4o6().setIface4o6(out_bindings[2]->getString());
}
// 4o6_interface_id
if (!out_bindings[3]->amNull()) {
std::string dhcp4o6_interface_id = out_bindings[3]->getString();
@ -383,6 +390,7 @@ public:
Option::create(Option::V6, D6O_INTERFACE_ID, dhcp4o6_interface_id_buf);
last_subnet->get4o6().setInterfaceId(option_dhcp4o6_interface_id);
}
// 4o6_subnet
if (!out_bindings[4]->amNull()) {
std::pair<IOAddress, uint8_t> dhcp4o6_subnet_prefix_pair =
@ -390,6 +398,7 @@ public:
last_subnet->get4o6().setSubnet4o6(dhcp4o6_subnet_prefix_pair.first,
dhcp4o6_subnet_prefix_pair.second);
}
// boot_file_name
if (!out_bindings[5]->amNull()) {
last_subnet->setFilename(out_bindings[5]->getString());
@ -399,6 +408,7 @@ public:
if (!out_bindings[6]->amNull()) {
last_subnet->allowClientClass(out_bindings[6]->getString());
}
// interface
if (!out_bindings[7]->amNull()) {
last_subnet->setIface(out_bindings[7]->getString());
@ -450,10 +460,9 @@ public:
}
}
// reservation_mode
// reservations_global
if (!out_bindings[15]->amNull()) {
last_subnet->setHostReservationMode(static_cast<Network::HRMode>
(out_bindings[15]->getInteger<uint8_t>()));
last_subnet->setReservationsGlobal(out_bindings[15]->getBool());
}
// server_hostname
@ -492,42 +501,46 @@ public:
last_subnet->setAuthoritative(out_bindings[52]->getBool());
}
// {min,max}_valid_lifetime
// pool client_class, require_client_classes and user_context
// ddns_send_updates at 58
// ddns_send_updates
if (!out_bindings[58]->amNull()) {
last_subnet->setDdnsSendUpdates(out_bindings[58]->getBool());
}
// ddns_override_no_update at 59
// ddns_override_no_update
if (!out_bindings[59]->amNull()) {
last_subnet->setDdnsOverrideNoUpdate(out_bindings[59]->getBool());
}
// ddns_override_client_update at 60
// ddns_override_client_update
if (!out_bindings[60]->amNull()) {
last_subnet->setDdnsOverrideClientUpdate(out_bindings[60]->getBool());
}
// ddns_replace_client_name at 61
// ddns_replace_client_name
if (!out_bindings[61]->amNull()) {
last_subnet->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
(out_bindings[61]->getInteger<uint8_t>()));
}
// ddns_generated_prefix at 62
// ddns_generated_prefix
if (!out_bindings[62]->amNull()) {
last_subnet->setDdnsGeneratedPrefix(out_bindings[62]->getString());
}
// ddns_qualifying_suffix at 63
// ddns_qualifying_suffix
if (!out_bindings[63]->amNull()) {
last_subnet->setDdnsQualifyingSuffix(out_bindings[63]->getString());
}
// server_tag at 64
// reservations_in_subnet
if (!out_bindings[64]->amNull()) {
last_subnet->setReservationsInSubnet(out_bindings[64]->getBool());
}
// reservations_out_of_pool
if (!out_bindings[65]->amNull()) {
last_subnet->setReservationsOutOfPool(out_bindings[65]->getBool());
}
// Subnet ready. Add it to the list.
auto ret = subnets.insert(last_subnet);
@ -541,14 +554,16 @@ public:
}
// Check for new server tags.
if (!out_bindings[64]->amNull() &&
(last_tag != out_bindings[64]->getString())) {
last_tag = out_bindings[64]->getString();
if (!out_bindings[66]->amNull() &&
(last_tag != out_bindings[66]->getString())) {
last_tag = out_bindings[66]->getString();
if (!last_tag.empty() && !last_subnet->hasServerTag(ServerTag(last_tag))) {
last_subnet->setServerTag(last_tag);
}
}
// Pool is between 20 and 25 with extra between 55 and 57
// If the row contains information about the pool and it appears to be
// new pool entry (checked by comparing pool id), let's create the new
// pool and add it to the subnet.
@ -591,7 +606,7 @@ public:
last_subnet->addPool(last_pool);
}
// Parse pool specific option.
// Parse pool specific option between 25 and 36
if (last_pool && !out_bindings[25]->amNull() &&
(last_pool_option_id < out_bindings[25]->getInteger<uint64_t>())) {
last_pool_option_id = out_bindings[25]->getInteger<uint64_t>();
@ -602,7 +617,7 @@ public:
}
}
// Parse subnet specific option.
// Parse subnet specific option between 37 and 48
if (!out_bindings[37]->amNull() &&
(last_option_id < out_bindings[37]->getInteger<uint64_t>())) {
last_option_id = out_bindings[37]->getInteger<uint64_t>();
@ -797,12 +812,12 @@ public:
last_pool = Pool4::create(IOAddress(out_bindings[1]->getInteger<uint32_t>()),
IOAddress(out_bindings[2]->getInteger<uint32_t>()));
// pool client_class (4)
// pool client_class
if (!out_bindings[4]->amNull()) {
last_pool->allowClientClass(out_bindings[4]->getString());
}
// pool require_client_classes (5)
// pool require_client_classes
ElementPtr require_element = out_bindings[5]->getJSON();
if (require_element) {
if (require_element->getType() != Element::list) {
@ -819,19 +834,17 @@ public:
}
}
// pool user_context (6)
// pool user_context
ElementPtr user_context = out_bindings[6]->getJSON();
if (user_context) {
last_pool->setContext(user_context);
}
// pool: modification_ts (7)
pools.push_back(last_pool);
pool_ids.push_back(last_pool_id);
}
// Parse pool specific option (8).
// Parse pool specific option between 8 and 19
if (last_pool && !out_bindings[8]->amNull() &&
(last_pool_option_id < out_bindings[8]->getInteger<uint64_t>())) {
last_pool_option_id = out_bindings[8]->getInteger<uint64_t>();
@ -937,16 +950,6 @@ public:
required_classes_element->add(Element::create(*required_class));
}
// Create binding for host reservation mode.
MySqlBindingPtr hr_mode_binding;
auto hr_mode = subnet->getHostReservationMode(Network::Inheritance::NONE);
if (!hr_mode.unspecified()) {
hr_mode_binding = MySqlBinding::createInteger<uint8_t>(static_cast<uint8_t>
(hr_mode.get()));
} else {
hr_mode_binding = MySqlBinding::createNull();
}
// Create binding for DDNS replace client name mode.
MySqlBindingPtr ddns_rcn_mode_binding;
auto ddns_rcn_mode = subnet->getDdnsReplaceClientNameMode(Network::Inheritance::NONE);
@ -1001,7 +1004,7 @@ public:
createInputRelayBinding(subnet),
createBinding(subnet->getT1(Network::Inheritance::NONE)),
createInputRequiredClassesBinding(subnet),
hr_mode_binding,
MySqlBinding::condCreateBool(subnet->getReservationsGlobal(Network::Inheritance::NONE)),
MySqlBinding::condCreateString(subnet->getSname(Network::Inheritance::NONE)),
shared_network_binding,
createInputContextBinding(subnet),
@ -1017,7 +1020,9 @@ public:
MySqlBinding::condCreateBool(subnet->getDdnsOverrideClientUpdate(Network::Inheritance::NONE)),
ddns_rcn_mode_binding,
MySqlBinding::condCreateString(subnet->getDdnsGeneratedPrefix(Network::Inheritance::NONE)),
MySqlBinding::condCreateString(subnet->getDdnsQualifyingSuffix(Network::Inheritance::NONE))
MySqlBinding::condCreateString(subnet->getDdnsQualifyingSuffix(Network::Inheritance::NONE)),
MySqlBinding::condCreateBool(subnet->getReservationsInSubnet(Network::Inheritance::NONE)),
MySqlBinding::condCreateBool(subnet->getReservationsOutOfPool(Network::Inheritance::NONE))
};
MySqlTransaction transaction(conn_);
@ -1231,7 +1236,7 @@ public:
MySqlBinding::createString(RELAY_BUF_LENGTH), // relay
MySqlBinding::createInteger<uint32_t>(), // renew_timer
MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // require_client_classes
MySqlBinding::createInteger<uint8_t>(), // reservation_mode
MySqlBinding::createInteger<uint8_t>(), // reservations_global
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
MySqlBinding::createInteger<uint32_t>(), // valid_lifetime
MySqlBinding::createInteger<uint64_t>(), // option: option_id
@ -1261,6 +1266,8 @@ public:
MySqlBinding::createInteger<uint8_t>(), // ddns_replace_client_name
MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_generated_prefix
MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_qualifying_suffix
MySqlBinding::createInteger<uint8_t>(), // reservations_in_subnet
MySqlBinding::createInteger<uint8_t>(), // reservations_out_of_pool
MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
};
@ -1352,10 +1359,9 @@ public:
}
}
// reservation_mode
// reservations_global
if (!out_bindings[10]->amNull()) {
last_network->setHostReservationMode(static_cast<Network::HRMode>
(out_bindings[10]->getIntegerOrDefault<uint8_t>(Network::HR_ALL)));
last_network->setReservationsGlobal(out_bindings[10]->getBool());
}
// user_context
@ -1408,37 +1414,47 @@ public:
// {min,max}_valid_lifetime
// ddns_send_updates at 34
// ddns_send_updates
if (!out_bindings[34]->amNull()) {
last_network->setDdnsSendUpdates(out_bindings[34]->getBool());
}
// ddns_override_no_update at 35
// ddns_override_no_update
if (!out_bindings[35]->amNull()) {
last_network->setDdnsOverrideNoUpdate(out_bindings[35]->getBool());
}
// ddns_override_client_update at 36
// ddns_override_client_update
if (!out_bindings[36]->amNull()) {
last_network->setDdnsOverrideClientUpdate(out_bindings[36]->getBool());
}
// ddns_replace_client_name at 37
// ddns_replace_client_name
if (!out_bindings[37]->amNull()) {
last_network->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
(out_bindings[37]->getInteger<uint8_t>()));
}
// ddns_generated_prefix at 38
// ddns_generated_prefix
if (!out_bindings[38]->amNull()) {
last_network->setDdnsGeneratedPrefix(out_bindings[38]->getString());
}
// ddns_qualifying_suffix at 39
// ddns_qualifying_suffix
if (!out_bindings[39]->amNull()) {
last_network->setDdnsQualifyingSuffix(out_bindings[39]->getString());
}
// reservations_in_subnet
if (!out_bindings[40]->amNull()) {
last_network->setReservationsInSubnet(out_bindings[40]->getBool());
}
// reservations_out_of_pool
if (!out_bindings[41]->amNull()) {
last_network->setReservationsOutOfPool(out_bindings[41]->getBool());
}
// Add the shared network.
auto ret = shared_networks.push_back(last_network);
@ -1451,15 +1467,15 @@ public:
}
// Check for new server tags.
if (!out_bindings[40]->amNull() &&
(last_tag != out_bindings[40]->getString())) {
last_tag = out_bindings[40]->getString();
if (!out_bindings[42]->amNull() &&
(last_tag != out_bindings[42]->getString())) {
last_tag = out_bindings[42]->getString();
if (!last_tag.empty() && !last_network->hasServerTag(ServerTag(last_tag))) {
last_network->setServerTag(last_tag);
}
}
// Parse option.
// Parse option from 13 to 24
if (!out_bindings[13]->amNull() &&
(last_option_id < out_bindings[13]->getInteger<uint64_t>())) {
last_option_id = out_bindings[13]->getInteger<uint64_t>();
@ -1569,16 +1585,6 @@ public:
" assigning it to a server or all servers is not supported");
}
// Create binding for host reservation mode.
MySqlBindingPtr hr_mode_binding;
auto hr_mode = shared_network->getHostReservationMode(Network::Inheritance::NONE);
if (!hr_mode.unspecified()) {
hr_mode_binding = MySqlBinding::createInteger<uint8_t>(static_cast<uint8_t>
(hr_mode.get()));
} else {
hr_mode_binding = MySqlBinding::createNull();
}
// Create binding for DDNS replace client name mode.
MySqlBindingPtr ddns_rcn_mode_binding;
auto ddns_rcn_mode = shared_network->getDdnsReplaceClientNameMode(Network::Inheritance::NONE);
@ -1599,7 +1605,7 @@ public:
createInputRelayBinding(shared_network),
createBinding(shared_network->getT1(Network::Inheritance::NONE)),
createInputRequiredClassesBinding(shared_network),
hr_mode_binding,
MySqlBinding::condCreateBool(shared_network->getReservationsGlobal(Network::Inheritance::NONE)),
createInputContextBinding(shared_network),
createBinding(shared_network->getValid(Network::Inheritance::NONE)),
createMinBinding(shared_network->getValid(Network::Inheritance::NONE)),
@ -1616,7 +1622,9 @@ public:
MySqlBinding::condCreateBool(shared_network->getDdnsOverrideClientUpdate(Network::Inheritance::NONE)),
ddns_rcn_mode_binding,
MySqlBinding::condCreateString(shared_network->getDdnsGeneratedPrefix(Network::Inheritance::NONE)),
MySqlBinding::condCreateString(shared_network->getDdnsQualifyingSuffix(Network::Inheritance::NONE))
MySqlBinding::condCreateString(shared_network->getDdnsQualifyingSuffix(Network::Inheritance::NONE)),
MySqlBinding::condCreateBool(shared_network->getReservationsInSubnet(Network::Inheritance::NONE)),
MySqlBinding::condCreateBool(shared_network->getReservationsOutOfPool(Network::Inheritance::NONE))
};
MySqlTransaction transaction(conn_);
@ -2448,7 +2456,7 @@ TaggedStatementArray tagged_statements = { {
" relay,"
" renew_timer,"
" require_client_classes,"
" reservation_mode,"
" reservations_global,"
" server_hostname,"
" shared_network_name,"
" user_context,"
@ -2464,9 +2472,11 @@ TaggedStatementArray tagged_statements = { {
" ddns_override_client_update,"
" ddns_replace_client_name,"
" ddns_generated_prefix,"
" ddns_qualifying_suffix"
" ddns_qualifying_suffix,"
" reservations_in_subnet,"
" reservations_out_of_pool"
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,"
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" },
"?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" },
// Insert association of the subnet with a server.
{ MySqlConfigBackendDHCPv4Impl::INSERT_SUBNET4_SERVER,
@ -2490,7 +2500,7 @@ TaggedStatementArray tagged_statements = { {
" relay,"
" renew_timer,"
" require_client_classes,"
" reservation_mode,"
" reservations_global,"
" user_context,"
" valid_lifetime,"
" min_valid_lifetime,"
@ -2507,9 +2517,11 @@ TaggedStatementArray tagged_statements = { {
" ddns_override_client_update,"
" ddns_replace_client_name,"
" ddns_generated_prefix,"
" ddns_qualifying_suffix"
" ddns_qualifying_suffix,"
" reservations_in_subnet,"
" reservations_out_of_pool"
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,"
" ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" },
" ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" },
// Insert association of the shared network with a server.
{ MySqlConfigBackendDHCPv4Impl::INSERT_SHARED_NETWORK4_SERVER,
@ -2564,7 +2576,7 @@ TaggedStatementArray tagged_statements = { {
" relay = ?,"
" renew_timer = ?,"
" require_client_classes = ?,"
" reservation_mode = ?,"
" reservations_global = ?,"
" server_hostname = ?,"
" shared_network_name = ?,"
" user_context = ?,"
@ -2580,7 +2592,9 @@ TaggedStatementArray tagged_statements = { {
" ddns_override_client_update = ?,"
" ddns_replace_client_name = ?,"
" ddns_generated_prefix = ?,"
" ddns_qualifying_suffix = ? "
" ddns_qualifying_suffix = ?,"
" reservations_in_subnet = ?,"
" reservations_out_of_pool = ? "
"WHERE subnet_id = ? OR subnet_prefix = ?" },
// Update existing shared network.
@ -2595,7 +2609,7 @@ TaggedStatementArray tagged_statements = { {
" relay = ?,"
" renew_timer = ?,"
" require_client_classes = ?,"
" reservation_mode = ?,"
" reservations_global = ?,"
" user_context = ?,"
" valid_lifetime = ?,"
" min_valid_lifetime = ?,"
@ -2612,7 +2626,9 @@ TaggedStatementArray tagged_statements = { {
" ddns_override_client_update = ?,"
" ddns_replace_client_name = ?,"
" ddns_generated_prefix = ?,"
" ddns_qualifying_suffix = ? "
" ddns_qualifying_suffix = ?,"
" reservations_in_subnet = ?,"
" reservations_out_of_pool = ? "
"WHERE name = ?" },
// Update existing option definition.

View File

@ -274,7 +274,7 @@ public:
MySqlBinding::createString(RELAY_BUF_LENGTH), // relay
MySqlBinding::createInteger<uint32_t>(), // renew_timer
MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // require_client_classes
MySqlBinding::createInteger<uint8_t>(), // reservation_mode
MySqlBinding::createInteger<uint8_t>(), // reservations_global
MySqlBinding::createString(SHARED_NETWORK_NAME_BUF_LENGTH), // shared_network_name
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
MySqlBinding::createInteger<uint32_t>(), // valid_lifetime
@ -350,6 +350,8 @@ public:
MySqlBinding::createInteger<uint8_t>(), // ddns_replace_client_name
MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_generated_prefix
MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_qualifying_suffix
MySqlBinding::createInteger<uint8_t>(), // reservations_in_subnet
MySqlBinding::createInteger<uint8_t>(), // reservations_out_of_pool
MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
};
@ -392,10 +394,10 @@ public:
last_pd_pool.reset();
last_tag.clear();
// subnet_id (0)
// subnet_id
SubnetID subnet_id(out_bindings[0]->getInteger<uint32_t>());
// subnet_prefix (1)
// subnet_prefix
std::string subnet_prefix = out_bindings[1]->getString();
auto prefix_pair = Subnet6::parsePrefix(subnet_prefix);
@ -404,10 +406,10 @@ public:
out_bindings[69],
out_bindings[70]);
// renew_timer (9)
// renew_timer
auto renew_timer = createTriplet(out_bindings[9]);
// rebind_timer (7)
// rebind_timer
auto rebind_timer = createTriplet(out_bindings[7]);
// valid_lifetime (and {min,max)_valid_lifetime)
@ -421,28 +423,25 @@ public:
preferred_lifetime,
valid_lifetime, subnet_id);
// client_class (2)
// client_class
if (!out_bindings[2]->amNull()) {
last_subnet->allowClientClass(out_bindings[2]->getString());
}
// interface (3)
// interface
if (!out_bindings[3]->amNull()) {
last_subnet->setIface(out_bindings[3]->getString());
}
// modification_ts (4)
// modification_ts
last_subnet->setModificationTime(out_bindings[4]->getTimestamp());
// 5 is preferred_lifetime
// rapid_commit (6)
// rapid_commit
if (!out_bindings[6]->amNull()) {
last_subnet->setRapidCommit(out_bindings[6]->getBool());
}
// 7 is rebind_timer
// relay (8)
// relay
ElementPtr relay_element = out_bindings[8]->getJSON();
if (relay_element) {
if (relay_element->getType() != Element::list) {
@ -458,9 +457,7 @@ public:
}
}
// 9 is renew_timer
// require_client_classes (10)
// require_client_classes
ElementPtr require_element = out_bindings[10]->getJSON();
if (require_element) {
if (require_element->getType() != Element::list) {
@ -477,41 +474,38 @@ public:
}
}
// reservation_mode (11)
// reservations_global
if (!out_bindings[11]->amNull()) {
last_subnet->setHostReservationMode(static_cast<Network::HRMode>
(out_bindings[11]->getInteger<uint8_t>()));
last_subnet->setReservationsGlobal(out_bindings[11]->getBool());
}
// shared_network_name (12)
// shared_network_name
if (!out_bindings[12]->amNull()) {
last_subnet->setSharedNetworkName(out_bindings[12]->getString());
}
// user_context (13)
// user_context
ElementPtr user_context = out_bindings[13]->getJSON();
if (user_context) {
last_subnet->setContext(user_context);
}
// 14 is valid_lifetime
// calculate_tee_times (65)
// calculate_tee_times
if (!out_bindings[65]->amNull()) {
last_subnet->setCalculateTeeTimes(out_bindings[65]->getBool());
}
// t1_percent (66)
// t1_percent
if (!out_bindings[66]->amNull()) {
last_subnet->setT1Percent(out_bindings[66]->getFloat());
}
// t2_percent (67)
// t2_percent
if (!out_bindings[67]->amNull()) {
last_subnet->setT2Percent(out_bindings[67]->getFloat());
}
// interface_id (68)
// interface_id
if (!out_bindings[68]->amNull()) {
auto iface_id_data = out_bindings[68]->getBlob();
if (!iface_id_data.empty()) {
@ -521,51 +515,46 @@ public:
}
}
// 69 and 70 are {min,max}_preferred_lifetime
// 71 and 72 are {min,max}_valid_lifetime
// 73 is pool client_class
// 74 is pool require_client_classes
// 75 is pool user_context
// 76 is pd pool excluded_prefix
// 77 is pd pool excluded_prefix_length
// 78 is pd pool client_class
// 79 is pd pool require_client_classes
// 80 is pd pool user_context
// ddns_send_updates (81)
// ddns_send_updates
if (!out_bindings[81]->amNull()) {
last_subnet->setDdnsSendUpdates(out_bindings[81]->getBool());
}
// ddns_override_no_update (82)
// ddns_override_no_update
if (!out_bindings[82]->amNull()) {
last_subnet->setDdnsOverrideNoUpdate(out_bindings[82]->getBool());
}
// ddns_override_client_update (83)
// ddns_override_client_update
if (!out_bindings[83]->amNull()) {
last_subnet->setDdnsOverrideClientUpdate(out_bindings[83]->getBool());
}
// ddns_replace_client_name (84)
// ddns_replace_client_name
if (!out_bindings[84]->amNull()) {
last_subnet->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
(out_bindings[84]->getInteger<uint8_t>()));
}
// ddns_generated_prefix (85)
// ddns_generated_prefix
if (!out_bindings[85]->amNull()) {
last_subnet->setDdnsGeneratedPrefix(out_bindings[85]->getString());
}
// ddns_qualifying_suffix (86)
// ddns_qualifying_suffix
if (!out_bindings[86]->amNull()) {
last_subnet->setDdnsQualifyingSuffix(out_bindings[86]->getString());
}
// server_tag (87 / last)
// reservations_in_subnet
if (!out_bindings[87]->amNull()) {
last_subnet->setReservationsInSubnet(out_bindings[87]->getBool());
}
// reservations_out_of_pool
if (!out_bindings[88]->amNull()) {
last_subnet->setReservationsOutOfPool(out_bindings[88]->getBool());
}
// Subnet ready. Add it to the list.
auto ret = subnets.insert(last_subnet);
@ -579,9 +568,9 @@ public:
}
// Check for new server tags.
if (!out_bindings[87]->amNull() &&
(last_tag != out_bindings[87]->getString())) {
last_tag = out_bindings[87]->getString();
if (!out_bindings[89]->amNull() &&
(last_tag != out_bindings[89]->getString())) {
last_tag = out_bindings[89]->getString();
if (!last_tag.empty() && !last_subnet->hasServerTag(ServerTag(last_tag))) {
last_subnet->setServerTag(last_tag);
}
@ -601,12 +590,12 @@ public:
last_pool = Pool6::create(Lease::TYPE_NA,
IOAddress(out_bindings[16]->getString()),
IOAddress(out_bindings[17]->getString()));
// pool client_class (73)
// pool client_class
if (!out_bindings[73]->amNull()) {
last_pool->allowClientClass(out_bindings[73]->getString());
}
// pool require_client_classes (74)
// pool require_client_classes
ElementPtr require_element = out_bindings[74]->getJSON();
if (require_element) {
if (require_element->getType() != Element::list) {
@ -623,7 +612,7 @@ public:
}
}
// pool user_context (75)
// pool user_context
ElementPtr user_context = out_bindings[75]->getJSON();
if (user_context) {
last_pool->setContext(user_context);
@ -645,7 +634,7 @@ public:
(out_bindings[20]->getInteger<uint64_t>() > last_pd_pool_id)) {
last_pd_pool_id = out_bindings[20]->getInteger<uint64_t>();
// excluded_prefix (76) and excluded_prefix_length (77)
// excluded_prefix and excluded_prefix_length
IOAddress excluded_prefix = IOAddress::IPV6_ZERO_ADDRESS();
if (!out_bindings[76]->amNull()) {
excluded_prefix = IOAddress(out_bindings[76]->getString());
@ -655,12 +644,12 @@ public:
out_bindings[23]->getInteger<uint8_t>(),
excluded_prefix,
out_bindings[77]->getInteger<uint8_t>());
// pd pool client_class (78)
// pd pool client_class
if (!out_bindings[78]->amNull()) {
last_pd_pool->allowClientClass(out_bindings[78]->getString());
}
// pd pool require_client_classes (79)
// pd pool require_client_classes
ElementPtr require_element = out_bindings[79]->getJSON();
if (require_element) {
if (require_element->getType() != Element::list) {
@ -677,7 +666,7 @@ public:
}
}
// pd pool user_context (80)
// pd pool user_context
ElementPtr user_context = out_bindings[80]->getJSON();
if (user_context) {
last_pd_pool->setContext(user_context);
@ -904,12 +893,12 @@ public:
last_pool = Pool6::create(Lease::TYPE_NA,
IOAddress(out_bindings[1]->getString()),
IOAddress(out_bindings[2]->getString()));
// pool client_class (4)
// pool client_class
if (!out_bindings[4]->amNull()) {
last_pool->allowClientClass(out_bindings[4]->getString());
}
// pool require_client_classes (5)
// pool require_client_classes
ElementPtr require_element = out_bindings[5]->getJSON();
if (require_element) {
if (require_element->getType() != Element::list) {
@ -926,19 +915,17 @@ public:
}
}
// pool user_context (6)
// pool user_context
ElementPtr user_context = out_bindings[6]->getJSON();
if (user_context) {
last_pool->setContext(user_context);
}
// pool: modification_ts (7)
pools.push_back(last_pool);
pool_ids.push_back(last_pool_id);
}
// Parse pool specific option (8).
// Parse pool specific option between 8 and 20
if (last_pool && !out_bindings[8]->amNull() &&
(last_pool_option_id < out_bindings[8]->getInteger<uint64_t>())) {
last_pool_option_id = out_bindings[8]->getInteger<uint64_t>();
@ -1007,7 +994,7 @@ public:
last_pd_pool_id = out_bindings[0]->getInteger<uint64_t>();
// excluded_prefix (5) and excluded_prefix_length (6)
// excluded_prefix and excluded_prefix_length
IOAddress excluded_prefix = IOAddress::IPV6_ZERO_ADDRESS();
if (!out_bindings[5]->amNull()) {
excluded_prefix = IOAddress(out_bindings[5]->getString());
@ -1019,12 +1006,12 @@ public:
excluded_prefix,
out_bindings[6]->getInteger<uint8_t>());
// pd pool client_class (7)
// pd pool client_class
if (!out_bindings[7]->amNull()) {
last_pd_pool->allowClientClass(out_bindings[7]->getString());
}
// pd pool require_client_classes (8)
// pd pool require_client_classes
ElementPtr require_element = out_bindings[8]->getJSON();
if (require_element) {
if (require_element->getType() != Element::list) {
@ -1041,19 +1028,17 @@ public:
}
}
// pd pool user_context (9)
// pd pool user_context
ElementPtr user_context = out_bindings[9]->getJSON();
if (user_context) {
last_pd_pool->setContext(user_context);
}
// pd pool modification_ts (10)
pd_pools.push_back(last_pd_pool);
pd_pool_ids.push_back(last_pd_pool_id);
}
// Parse pd pool specific option between 11 and 24
// Parse pd pool specific option between 11 and 23
if (last_pd_pool && !out_bindings[11]->amNull() &&
(last_pd_pool_option_id < out_bindings[11]->getInteger<uint64_t>())) {
last_pd_pool_option_id = out_bindings[11]->getInteger<uint64_t>();
@ -1178,16 +1163,6 @@ public:
required_classes_element->add(Element::create(*required_class));
}
// Create binding for host reservation mode.
MySqlBindingPtr hr_mode_binding;
auto hr_mode = subnet->getHostReservationMode(Network::Inheritance::NONE);
if (!hr_mode.unspecified()) {
hr_mode_binding = MySqlBinding::createInteger<uint8_t>(static_cast<uint8_t>
(hr_mode.get()));
} else {
hr_mode_binding = MySqlBinding::createNull();
}
// Create binding for DDNS replace client name mode.
MySqlBindingPtr ddns_rcn_mode_binding;
auto ddns_rcn_mode = subnet->getDdnsReplaceClientNameMode(Network::Inheritance::NONE);
@ -1251,7 +1226,7 @@ public:
createInputRelayBinding(subnet),
createBinding(subnet->getT1(Network::Inheritance::NONE)),
createInputRequiredClassesBinding(subnet),
hr_mode_binding,
MySqlBinding::condCreateBool(subnet->getReservationsGlobal(Network::Inheritance::NONE)),
shared_network_binding,
createInputContextBinding(subnet),
createBinding(subnet->getValid(Network::Inheritance::NONE)),
@ -1266,7 +1241,9 @@ public:
MySqlBinding::condCreateBool(subnet->getDdnsOverrideClientUpdate(Network::Inheritance::NONE)),
ddns_rcn_mode_binding,
MySqlBinding::condCreateString(subnet->getDdnsGeneratedPrefix(Network::Inheritance::NONE)),
MySqlBinding::condCreateString(subnet->getDdnsQualifyingSuffix(Network::Inheritance::NONE))
MySqlBinding::condCreateString(subnet->getDdnsQualifyingSuffix(Network::Inheritance::NONE)),
MySqlBinding::condCreateBool(subnet->getReservationsInSubnet(Network::Inheritance::NONE)),
MySqlBinding::condCreateBool(subnet->getReservationsOutOfPool(Network::Inheritance::NONE))
};
MySqlTransaction transaction(conn_);
@ -1556,7 +1533,7 @@ public:
MySqlBinding::createString(RELAY_BUF_LENGTH), // relay
MySqlBinding::createInteger<uint32_t>(), // renew_timer
MySqlBinding::createString(REQUIRE_CLIENT_CLASSES_BUF_LENGTH), // require_client_classes
MySqlBinding::createInteger<uint8_t>(), // reservation_mode
MySqlBinding::createInteger<uint8_t>(), // reservations_global
MySqlBinding::createString(USER_CONTEXT_BUF_LENGTH), // user_context
MySqlBinding::createInteger<uint32_t>(), // valid_lifetime
MySqlBinding::createInteger<uint64_t>(), // option: option_id
@ -1586,6 +1563,8 @@ public:
MySqlBinding::createInteger<uint8_t>(), // ddns_replace_client_name
MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_generated_prefix
MySqlBinding::createString(DNS_NAME_BUF_LENGTH), // ddns_qualifying_suffix
MySqlBinding::createInteger<uint8_t>(), // reservations_in_subnet
MySqlBinding::createInteger<uint8_t>(), // reservations_out_of_pool
MySqlBinding::createString(SERVER_TAG_BUF_LENGTH) // server_tag
};
@ -1684,10 +1663,9 @@ public:
}
}
// reservation_mode
// reservations_global
if (!out_bindings[11]->amNull()) {
last_network->setHostReservationMode(static_cast<Network::HRMode>
(out_bindings[11]->getIntegerOrDefault<uint8_t>(Network::HR_ALL)));
last_network->setReservationsGlobal(out_bindings[11]->getBool());
}
// user_context
@ -1732,38 +1710,46 @@ public:
// {min,max)_valid_lifetime
// ddns_send_updates at 35
// ddns_send_updates
if (!out_bindings[35]->amNull()) {
last_network->setDdnsSendUpdates(out_bindings[35]->getBool());
}
// ddns_override_no_update at 36
// ddns_override_no_update
if (!out_bindings[36]->amNull()) {
last_network->setDdnsOverrideNoUpdate(out_bindings[36]->getBool());
}
// ddns_override_client_update at 37
// ddns_override_client_update
if (!out_bindings[37]->amNull()) {
last_network->setDdnsOverrideClientUpdate(out_bindings[37]->getBool());
}
// ddns_replace_client_name at 38
// ddns_replace_client_name
if (!out_bindings[38]->amNull()) {
last_network->setDdnsReplaceClientNameMode(static_cast<D2ClientConfig::ReplaceClientNameMode>
(out_bindings[38]->getInteger<uint8_t>()));
}
// ddns_generated_prefix at 39
// ddns_generated_prefix
if (!out_bindings[39]->amNull()) {
last_network->setDdnsGeneratedPrefix(out_bindings[39]->getString());
}
// ddns_qualifying_suffix at 40
// ddns_qualifying_suffix
if (!out_bindings[40]->amNull()) {
last_network->setDdnsQualifyingSuffix(out_bindings[40]->getString());
}
// server_tag at 41
// reservations_in_subnet
if (!out_bindings[41]->amNull()) {
last_network->setReservationsInSubnet(out_bindings[41]->getBool());
}
// reservations_out_of_pool
if (!out_bindings[42]->amNull()) {
last_network->setReservationsOutOfPool(out_bindings[42]->getBool());
}
// Add the shared network.
auto ret = shared_networks.push_back(last_network);
@ -1788,9 +1774,9 @@ public:
}
// Check for new server tags.
if (!out_bindings[41]->amNull() &&
(last_tag != out_bindings[41]->getString())) {
last_tag = out_bindings[41]->getString();
if (!out_bindings[43]->amNull() &&
(last_tag != out_bindings[43]->getString())) {
last_tag = out_bindings[43]->getString();
if (!last_tag.empty() && !last_network->hasServerTag(ServerTag(last_tag))) {
last_network->setServerTag(last_tag);
}
@ -1895,16 +1881,6 @@ public:
" (unassigned) is unsupported at the moment");
}
// Create binding for host reservation mode.
MySqlBindingPtr hr_mode_binding;
auto hr_mode = shared_network->getHostReservationMode(Network::Inheritance::NONE);
if (!hr_mode.unspecified()) {
hr_mode_binding = MySqlBinding::createInteger<uint8_t>(static_cast<uint8_t>
(hr_mode.get()));
} else {
hr_mode_binding = MySqlBinding::createNull();
}
// Create the binding holding interface_id.
MySqlBindingPtr interface_id_binding = MySqlBinding::createNull();
auto opt_iface_id = shared_network->getInterfaceId();
@ -1939,7 +1915,7 @@ public:
createInputRelayBinding(shared_network),
createBinding(shared_network->getT1(Network::Inheritance::NONE)),
createInputRequiredClassesBinding(shared_network),
hr_mode_binding,
MySqlBinding::condCreateBool(shared_network->getReservationsGlobal(Network::Inheritance::NONE)),
createInputContextBinding(shared_network),
createBinding(shared_network->getValid(Network::Inheritance::NONE)),
createMinBinding(shared_network->getValid(Network::Inheritance::NONE)),
@ -1953,7 +1929,9 @@ public:
MySqlBinding::condCreateBool(shared_network->getDdnsOverrideClientUpdate(Network::Inheritance::NONE)),
ddns_rcn_mode_binding,
MySqlBinding::condCreateString(shared_network->getDdnsGeneratedPrefix(Network::Inheritance::NONE)),
MySqlBinding::condCreateString(shared_network->getDdnsQualifyingSuffix(Network::Inheritance::NONE))
MySqlBinding::condCreateString(shared_network->getDdnsQualifyingSuffix(Network::Inheritance::NONE)),
MySqlBinding::condCreateBool(shared_network->getReservationsInSubnet(Network::Inheritance::NONE)),
MySqlBinding::condCreateBool(shared_network->getReservationsOutOfPool(Network::Inheritance::NONE))
};
MySqlTransaction transaction(conn_);
@ -2911,7 +2889,7 @@ TaggedStatementArray tagged_statements = { {
" relay,"
" renew_timer,"
" require_client_classes,"
" reservation_mode,"
" reservations_global,"
" shared_network_name,"
" user_context,"
" valid_lifetime,"
@ -2926,9 +2904,11 @@ TaggedStatementArray tagged_statements = { {
" ddns_override_client_update,"
" ddns_replace_client_name,"
" ddns_generated_prefix,"
" ddns_qualifying_suffix"
" ddns_qualifying_suffix,"
" reservations_in_subnet,"
" reservations_out_of_pool"
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,"
" ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" },
" ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" },
// Insert association of the subnet with a server.
{ MySqlConfigBackendDHCPv6Impl::INSERT_SUBNET6_SERVER,
@ -2960,7 +2940,7 @@ TaggedStatementArray tagged_statements = { {
" relay,"
" renew_timer,"
" require_client_classes,"
" reservation_mode,"
" reservations_global,"
" user_context,"
" valid_lifetime,"
" min_valid_lifetime,"
@ -2974,9 +2954,11 @@ TaggedStatementArray tagged_statements = { {
" ddns_override_client_update,"
" ddns_replace_client_name,"
" ddns_generated_prefix,"
" ddns_qualifying_suffix"
" ddns_qualifying_suffix,"
" reservations_in_subnet,"
" reservations_out_of_pool"
") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,"
" ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" },
" ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" },
// Insert association of the shared network with a server.
{ MySqlConfigBackendDHCPv6Impl::INSERT_SHARED_NETWORK6_SERVER,
@ -3029,7 +3011,7 @@ TaggedStatementArray tagged_statements = { {
" relay = ?,"
" renew_timer = ?,"
" require_client_classes = ?,"
" reservation_mode = ?,"
" reservations_global = ?,"
" shared_network_name = ?,"
" user_context = ?,"
" valid_lifetime = ?,"
@ -3044,7 +3026,9 @@ TaggedStatementArray tagged_statements = { {
" ddns_override_client_update = ?,"
" ddns_replace_client_name = ?,"
" ddns_generated_prefix = ?,"
" ddns_qualifying_suffix = ? "
" ddns_qualifying_suffix = ?,"
" reservations_in_subnet = ?,"
" reservations_out_of_pool = ? "
"WHERE subnet_id = ? OR subnet_prefix = ?" },
// Update existing shared network.
@ -3062,7 +3046,7 @@ TaggedStatementArray tagged_statements = { {
" relay = ?,"
" renew_timer = ?,"
" require_client_classes = ?,"
" reservation_mode = ?,"
" reservations_global = ?,"
" user_context = ?,"
" valid_lifetime = ?,"
" min_valid_lifetime = ?,"
@ -3076,7 +3060,9 @@ TaggedStatementArray tagged_statements = { {
" ddns_override_client_update = ?,"
" ddns_replace_client_name = ?,"
" ddns_generated_prefix = ?,"
" ddns_qualifying_suffix = ? "
" ddns_qualifying_suffix = ?,"
" reservations_in_subnet = ?,"
" reservations_out_of_pool = ? "
"WHERE name = ?" },
// Update existing option definition.

View File

@ -66,7 +66,7 @@ namespace {
" s.relay," \
" s.renew_timer," \
" s.require_client_classes," \
" s.reservation_mode," \
" s.reservations_global," \
" s.server_hostname," \
" s.shared_network_name," \
" s.user_context," \
@ -115,6 +115,8 @@ namespace {
" s.ddns_replace_client_name," \
" s.ddns_generated_prefix," \
" s.ddns_qualifying_suffix," \
" s.reservations_in_subnet," \
" s.reservations_out_of_pool," \
" srv.tag " \
"FROM dhcp4_subnet AS s " \
server_join \
@ -164,7 +166,7 @@ namespace {
" s.relay," \
" s.renew_timer," \
" s.require_client_classes," \
" s.reservation_mode," \
" s.reservations_global," \
" s.shared_network_name," \
" s.user_context," \
" s.valid_lifetime," \
@ -240,6 +242,8 @@ namespace {
" s.ddns_replace_client_name," \
" s.ddns_generated_prefix," \
" s.ddns_qualifying_suffix," \
" s.reservations_in_subnet," \
" s.reservations_out_of_pool," \
" srv.tag " \
"FROM dhcp6_subnet AS s " \
server_join \
@ -415,7 +419,7 @@ namespace {
" n.relay," \
" n.renew_timer," \
" n.require_client_classes," \
" n.reservation_mode," \
" n.reservations_global," \
" n.user_context," \
" n.valid_lifetime," \
" o.option_id," \
@ -445,6 +449,8 @@ namespace {
" n.ddns_replace_client_name," \
" n.ddns_generated_prefix," \
" n.ddns_qualifying_suffix," \
" n.reservations_in_subnet," \
" n.reservations_out_of_pool," \
" s.tag " \
"FROM dhcp4_shared_network AS n " \
server_join \
@ -492,7 +498,7 @@ namespace {
" n.relay," \
" n.renew_timer," \
" n.require_client_classes," \
" n.reservation_mode," \
" n.reservations_global," \
" n.user_context," \
" n.valid_lifetime," \
" o.option_id," \
@ -522,6 +528,8 @@ namespace {
" n.ddns_replace_client_name," \
" n.ddns_generated_prefix," \
" n.ddns_qualifying_suffix," \
" n.reservations_in_subnet," \
" n.reservations_out_of_pool," \
" s.tag " \
"FROM dhcp6_shared_network AS n " \
server_join \

View File

@ -161,7 +161,9 @@ public:
subnet->setT1(1234);
subnet->requireClientClass("required-class1");
subnet->requireClientClass("required-class2");
subnet->setHostReservationMode(Subnet4::HR_DISABLED);
subnet->setReservationsGlobal(false);
subnet->setReservationsInSubnet(false);
subnet->setReservationsOutOfPool(false);
subnet->setSname("server-hostname");
subnet->setContext(user_context);
subnet->setValid(555555);
@ -260,7 +262,9 @@ public:
shared_network->setT1(1234);
shared_network->requireClientClass("required-class1");
shared_network->requireClientClass("required-class2");
shared_network->setHostReservationMode(Subnet4::HR_DISABLED);
shared_network->setReservationsGlobal(false);
shared_network->setReservationsInSubnet(false);
shared_network->setReservationsOutOfPool(false);
shared_network->setContext(user_context);
shared_network->setValid(5555);
shared_network->setCalculateTeeTimes(true);
@ -1319,8 +1323,14 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSubnet4WithOptionalUnspecified) {
EXPECT_TRUE(returned_subnet->getT2().unspecified());
EXPECT_EQ(0, returned_subnet->getT2().get());
EXPECT_TRUE(returned_subnet->getHostReservationMode().unspecified());
EXPECT_EQ(Network::HR_ALL, returned_subnet->getHostReservationMode().get());
EXPECT_TRUE(returned_subnet->getReservationsGlobal().unspecified());
EXPECT_FALSE(returned_subnet->getReservationsGlobal().get());
EXPECT_TRUE(returned_subnet->getReservationsInSubnet().unspecified());
EXPECT_TRUE(returned_subnet->getReservationsInSubnet().get());
EXPECT_TRUE(returned_subnet->getReservationsOutOfPool().unspecified());
EXPECT_FALSE(returned_subnet->getReservationsOutOfPool().get());
EXPECT_TRUE(returned_subnet->getCalculateTeeTimes().unspecified());
EXPECT_FALSE(returned_subnet->getCalculateTeeTimes().get());
@ -2338,8 +2348,14 @@ TEST_F(MySqlConfigBackendDHCPv4Test, getSharedNetwork4WithOptionalUnspecified) {
EXPECT_TRUE(returned_network->getT2().unspecified());
EXPECT_EQ(0, returned_network->getT2().get());
EXPECT_TRUE(returned_network->getHostReservationMode().unspecified());
EXPECT_EQ(Network::HR_ALL, returned_network->getHostReservationMode().get());
EXPECT_TRUE(returned_network->getReservationsGlobal().unspecified());
EXPECT_FALSE(returned_network->getReservationsGlobal().get());
EXPECT_TRUE(returned_network->getReservationsInSubnet().unspecified());
EXPECT_TRUE(returned_network->getReservationsInSubnet().get());
EXPECT_TRUE(returned_network->getReservationsOutOfPool().unspecified());
EXPECT_FALSE(returned_network->getReservationsOutOfPool().get());
EXPECT_TRUE(returned_network->getCalculateTeeTimes().unspecified());
EXPECT_FALSE(returned_network->getCalculateTeeTimes().get());

View File

@ -157,7 +157,9 @@ public:
subnet->setT1(1234);
subnet->requireClientClass("required-class1");
subnet->requireClientClass("required-class2");
subnet->setHostReservationMode(Subnet4::HR_DISABLED);
subnet->setReservationsGlobal(false);
subnet->setReservationsInSubnet(false);
subnet->setReservationsOutOfPool(false);
subnet->setContext(user_context);
subnet->setValid(555555);
subnet->setPreferred(4444444);
@ -307,7 +309,9 @@ public:
shared_network->setT1(1234);
shared_network->requireClientClass("required-class1");
shared_network->requireClientClass("required-class2");
shared_network->setHostReservationMode(Subnet6::HR_DISABLED);
shared_network->setReservationsGlobal(false);
shared_network->setReservationsInSubnet(false);
subnet->setReservationsOutOfPool(false);
shared_network->setContext(user_context);
shared_network->setValid(5555);
shared_network->setPreferred(4444);
@ -1367,8 +1371,14 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSubnet6WithOptionalUnspecified) {
EXPECT_TRUE(returned_subnet->getT2().unspecified());
EXPECT_EQ(0, returned_subnet->getT2().get());
EXPECT_TRUE(returned_subnet->getHostReservationMode().unspecified());
EXPECT_EQ(Network::HR_ALL, returned_subnet->getHostReservationMode().get());
EXPECT_TRUE(returned_subnet->getReservationsGlobal().unspecified());
EXPECT_FALSE(returned_subnet->getReservationsGlobal().get());
EXPECT_TRUE(returned_subnet->getReservationsInSubnet().unspecified());
EXPECT_TRUE(returned_subnet->getReservationsInSubnet().get());
EXPECT_TRUE(returned_subnet->getReservationsOutOfPool().unspecified());
EXPECT_FALSE(returned_subnet->getReservationsOutOfPool().get());
EXPECT_TRUE(returned_subnet->getCalculateTeeTimes().unspecified());
EXPECT_FALSE(returned_subnet->getCalculateTeeTimes().get());
@ -2376,8 +2386,14 @@ TEST_F(MySqlConfigBackendDHCPv6Test, getSharedNetwork6WithOptionalUnspecified) {
EXPECT_TRUE(returned_network->getT2().unspecified());
EXPECT_EQ(0, returned_network->getT2().get());
EXPECT_TRUE(returned_network->getHostReservationMode().unspecified());
EXPECT_EQ(Network::HR_ALL, returned_network->getHostReservationMode().get());
EXPECT_TRUE(returned_network->getReservationsGlobal().unspecified());
EXPECT_FALSE(returned_network->getReservationsGlobal().get());
EXPECT_TRUE(returned_network->getReservationsInSubnet().unspecified());
EXPECT_TRUE(returned_network->getReservationsInSubnet().get());
EXPECT_TRUE(returned_network->getReservationsOutOfPool().unspecified());
EXPECT_FALSE(returned_network->getReservationsOutOfPool().get());
EXPECT_TRUE(returned_network->getCalculateTeeTimes().unspecified());
EXPECT_FALSE(returned_network->getCalculateTeeTimes().get());

View File

@ -535,7 +535,7 @@ isAllocated(const asiolink::IOAddress& prefix, const uint8_t prefix_len) const {
ConstHostPtr
AllocEngine::ClientContext6::currentHost() const {
Subnet6Ptr subnet = host_subnet_ ? host_subnet_ : subnet_;
if (subnet && (subnet_->getHostReservationMode() & Network::HR_IN_SUBNET_FLAG)) {
if (subnet && subnet->getReservationsInSubnet()) {
auto host = hosts_.find(subnet->getID());
if (host != hosts_.cend()) {
return (host->second);
@ -548,7 +548,7 @@ AllocEngine::ClientContext6::currentHost() const {
ConstHostPtr
AllocEngine::ClientContext6::globalHost() const {
Subnet6Ptr subnet = host_subnet_ ? host_subnet_ : subnet_;
if (subnet && (subnet_->getHostReservationMode() & Network::HR_GLOBAL_FLAG)) {
if (subnet && subnet_->getReservationsGlobal()) {
auto host = hosts_.find(SUBNET_ID_GLOBAL);
if (host != hosts_.cend()) {
return (host->second);
@ -597,14 +597,14 @@ AllocEngine::findReservation(ClientContext6& ctx) {
SharedNetwork6Ptr network;
subnet->getSharedNetwork(network);
if (subnet->getHostReservationMode() & Network::HR_GLOBAL_FLAG) {
if (subnet->getReservationsGlobal()) {
ConstHostPtr ghost = findGlobalReservation(ctx);
if (ghost) {
ctx.hosts_[SUBNET_ID_GLOBAL] = ghost;
// @todo In theory, to support global as part of HR_ALL,
// we would just keep going, instead of returning.
if (subnet->getHostReservationMode() == Network::HR_GLOBAL) {
// If we had only to fetch global reservations it is done.
if (!subnet->getReservationsInSubnet() &&
!subnet->getReservationsOutOfPool()) {
return;
}
}
@ -641,9 +641,9 @@ AllocEngine::findReservation(ClientContext6& ctx) {
while (subnet) {
// Only makes sense to get reservations if the client has access
// to the class and host reservations are enabled.
// to the class and host reservations are enabled for this subnet.
if (subnet->clientSupported(ctx.query_->getClasses()) &&
(subnet->getHostReservationMode() != Network::HR_DISABLED)) {
(subnet->getReservationsInSubnet() || subnet->getReservationsOutOfPool())) {
// Iterate over configured identifiers in the order of preference
// and try to use each of them to search for the reservations.
for (auto id_pair : ctx.host_identifiers_) {
@ -916,9 +916,6 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
continue;
}
// Check which host reservation mode is supported in this subnet.
Network::HRMode hr_mode = subnet->getHostReservationMode();
/// @todo: We support only one hint for now
Lease6Ptr lease =
LeaseMgrFactory::instance().getLease6(ctx.currentIA().type_, hint);
@ -929,9 +926,9 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
// it has been reserved for us we would have already allocated a lease.
ConstHostCollection hosts;
bool in_subnet = (hr_mode & Network::HR_IN_SUBNET_FLAG);
bool out_of_pool = (hr_mode & Network::HR_OUT_OF_POOL_FLAG);
// The HR_OUT_OF_POOL_FLAG indicates that no client should be assigned reservations
bool in_subnet = subnet->getReservationsInSubnet();
bool out_of_pool = subnet->getReservationsOutOfPool();
// The out-of-pool flag indicates that no client should be assigned reservations
// from within the dynamic pool, and for that reason we only look at reservations that
// are outside the pools, hence the inPool check.
if ((in_subnet && !out_of_pool) ||
@ -969,9 +966,9 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
// If the lease is expired, we may likely reuse it, but...
ConstHostCollection hosts;
bool in_subnet = (hr_mode & Network::HR_IN_SUBNET_FLAG);
bool out_of_pool = (hr_mode & Network::HR_OUT_OF_POOL_FLAG);
// The HR_OUT_OF_POOL_FLAG indicates that no client should be assigned reservations
bool in_subnet = subnet->getReservationsInSubnet();
bool out_of_pool = subnet->getReservationsOutOfPool();
// The out-of-pool flag indicates that no client should be assigned reservations
// from within the dynamic pool, and for that reason we only look at reservations that
// are outside the pools, hence the inPool check.
if ((in_subnet && !out_of_pool) ||
@ -1053,7 +1050,8 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
continue;
}
uint64_t max_attempts = (attempts_ > 0 ? attempts_ : possible_attempts);
Network::HRMode hr_mode = subnet->getHostReservationMode();
bool in_subnet = subnet->getReservationsInSubnet();
bool out_of_pool = subnet->getReservationsOutOfPool();
// Set the default status code in case the lease6_select callouts
// do not exist and the callout handle has a status returned by
@ -1084,8 +1082,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
}
// First check for reservation when it is the choice.
if (check_reservation_first && ((hr_mode & Network::HR_IN_SUBNET_FLAG) &&
!(hr_mode & Network::HR_OUT_OF_POOL_FLAG))) {
if (check_reservation_first && in_subnet && !out_of_pool) {
auto hosts = getIPv6Resrv(subnet->getID(), candidate);
if (!hosts.empty()) {
// Don't allocate.
@ -1110,8 +1107,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
/// In-pool reservations: Check if this address is reserved for someone
/// else. There is no need to check for whom it is reserved, because if
/// it has been reserved for us we would have already allocated a lease.
if (!check_reservation_first && (hr_mode & Network::HR_IN_SUBNET_FLAG) &&
!(hr_mode & Network::HR_OUT_OF_POOL_FLAG)) {
if (!check_reservation_first && in_subnet && !out_of_pool) {
auto hosts = getIPv6Resrv(subnet->getID(), candidate);
if (!hosts.empty()) {
// Don't allocate.
@ -1143,8 +1139,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
// allocation attempts.
} else if (existing->expired()) {
// Make sure it's not reserved.
if (!check_reservation_first && (hr_mode & Network::HR_IN_SUBNET_FLAG) &&
!(hr_mode & Network::HR_OUT_OF_POOL_FLAG)) {
if (!check_reservation_first && in_subnet && !out_of_pool) {
auto hosts = getIPv6Resrv(subnet->getID(), candidate);
if (!hosts.empty()) {
// Don't allocate.
@ -1265,11 +1260,8 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx,
ConstHostPtr host = ctx.hosts_[subnet_id];
// Check which host reservation mode is supported in this subnet.
Network::HRMode hr_mode = subnet->getHostReservationMode();
bool in_subnet = (hr_mode & Network::HR_IN_SUBNET_FLAG);
bool out_of_pool = (hr_mode & Network::HR_OUT_OF_POOL_FLAG);
bool in_subnet = subnet->getReservationsInSubnet();
bool out_of_pool = subnet->getReservationsOutOfPool();
// Get the IPv6 reservations of specified type.
const IPv6ResrvRange& reservs = host->getIPv6Reservations(type);
@ -1284,7 +1276,7 @@ AllocEngine::allocateReservedLeases6(ClientContext6& ctx,
continue;
}
// The HR_OUT_OF_POOL_FLAG indicates that no client should be assigned reservations
// The out-of-pool flag indicates that no client should be assigned reservations
// from within the dynamic pool, and for that reason we only look at reservations that
// are outside the pools, hence the inPool check.
if ((in_subnet && !out_of_pool) ||
@ -1490,7 +1482,9 @@ AllocEngine::removeNonmatchingReservedLeases6(ClientContext6& ctx,
}
// If host reservation is disabled (so there are no reserved leases)
// use the simplified version.
if (ctx.subnet_->getHostReservationMode() == Network::HR_DISABLED) {
if (!ctx.subnet_->getReservationsGlobal() &&
!ctx.subnet_->getReservationsInSubnet() &&
!ctx.subnet_->getReservationsOutOfPool()) {
removeNonmatchingReservedNoHostLeases6(ctx, existing_leases);
return;
}
@ -2978,11 +2972,9 @@ addressReserved(const IOAddress& address, const AllocEngine::ClientContext4& ctx
if (!ctx.subnet_) {
return false;
}
// Check which host reservation mode is supported in this subnet.
Network::HRMode hr_mode = ctx.subnet_->getHostReservationMode();
bool in_subnet = (hr_mode & Network::HR_IN_SUBNET_FLAG);
bool out_of_pool = (hr_mode & Network::HR_OUT_OF_POOL_FLAG);
// The HR_OUT_OF_POOL_FLAG indicates that no client should be assigned reservations
bool in_subnet = ctx.subnet_->getReservationsInSubnet();
bool out_of_pool = ctx.subnet_->getReservationsOutOfPool();
// The out-of-pool flag indicates that no client should be assigned reservations
// from within the dynamic pool, and for that reason we only look at reservations that
// are outside the pools, hence the inPool check.
if ((in_subnet && !out_of_pool) ||
@ -3048,13 +3040,14 @@ hasAddressReservation(AllocEngine::ClientContext4& ctx) {
Subnet4Ptr subnet = ctx.subnet_;
while (subnet) {
if (subnet->getHostReservationMode() & Network::HR_GLOBAL_FLAG) {
if (subnet->getReservationsGlobal()) {
auto host = ctx.hosts_.find(SUBNET_ID_GLOBAL);
bool found = (host != ctx.hosts_.end() &&
!(host->second->getIPv4Reservation().isV4Zero()));
// if we want global + other modes we would need to
// return only if true, else continue
if (subnet->getHostReservationMode() == Network::HR_GLOBAL) {
if (!subnet->getReservationsInSubnet() &&
!subnet->getReservationsOutOfPool()) {
return (found);
} else {
if (found) {
@ -3064,11 +3057,9 @@ hasAddressReservation(AllocEngine::ClientContext4& ctx) {
}
auto host = ctx.hosts_.find(subnet->getID());
// Check which host reservation mode is supported in this subnet.
Network::HRMode hr_mode = subnet->getHostReservationMode();
bool in_subnet = (hr_mode & Network::HR_IN_SUBNET_FLAG);
bool out_of_pool = (hr_mode & Network::HR_OUT_OF_POOL_FLAG);
// The HR_OUT_OF_POOL_FLAG indicates that no client should be assigned reservations
bool in_subnet = subnet->getReservationsInSubnet();
bool out_of_pool = subnet->getReservationsOutOfPool();
// The out-of-pool flag indicates that no client should be assigned reservations
// from within the dynamic pool, and for that reason we only look at reservations that
// are outside the pools, hence the inPool check.
if (host != ctx.hosts_.end()) {
@ -3252,7 +3243,7 @@ AllocEngine::ClientContext4::ClientContext4(const Subnet4Ptr& subnet,
ConstHostPtr
AllocEngine::ClientContext4::currentHost() const {
if (subnet_ && (subnet_->getHostReservationMode() & Network::HR_IN_SUBNET_FLAG)) {
if (subnet_ && subnet_->getReservationsInSubnet()) {
auto host = hosts_.find(subnet_->getID());
if (host != hosts_.cend()) {
return (host->second);
@ -3264,7 +3255,7 @@ AllocEngine::ClientContext4::currentHost() const {
ConstHostPtr
AllocEngine::ClientContext4::globalHost() const {
if (subnet_ && (subnet_->getHostReservationMode() & Network::HR_GLOBAL_FLAG)) {
if (subnet_ && subnet_->getReservationsGlobal()) {
auto host = hosts_.find(SUBNET_ID_GLOBAL);
if (host != hosts_.cend()) {
return (host->second);
@ -3351,14 +3342,14 @@ AllocEngine::findReservation(ClientContext4& ctx) {
SharedNetwork4Ptr network;
subnet->getSharedNetwork(network);
if (subnet->getHostReservationMode() & Network::HR_GLOBAL_FLAG) {
if (subnet->getReservationsGlobal()) {
ConstHostPtr ghost = findGlobalReservation(ctx);
if (ghost) {
ctx.hosts_[SUBNET_ID_GLOBAL] = ghost;
// @todo In theory, to support global as part of HR_ALL,
// we would just keep going, instead of returning.
if (subnet->getHostReservationMode() == Network::HR_GLOBAL) {
// If we had only to fetch global reservations it is done.
if (!subnet->getReservationsInSubnet() &&
!subnet->getReservationsOutOfPool()) {
return;
}
}
@ -3399,7 +3390,7 @@ AllocEngine::findReservation(ClientContext4& ctx) {
// Only makes sense to get reservations if the client has access
// to the class.
if (subnet->clientSupported(ctx.query_->getClasses()) &&
(subnet->getHostReservationMode() != Network::HR_DISABLED)) {
(subnet->getReservationsInSubnet() || subnet->getReservationsOutOfPool())) {
// Iterate over configured identifiers in the order of preference
// and try to use each of them to search for the reservations.
BOOST_FOREACH(const IdentifierPair& id_pair, ctx.host_identifiers_) {

View File

@ -7,7 +7,6 @@
#include <config.h>
#include <dhcpsrv/triplet.h>
#include <dhcpsrv/parsers/base_network_parser.h>
#include <dhcpsrv/parsers/reservation_modes_parser.h>
#include <util/optional.h>
#include <util/strutil.h>
@ -17,6 +16,44 @@ using namespace isc::util;
namespace isc {
namespace dhcp {
bool
BaseNetworkParser::moveReservationMode(ElementPtr config) {
if (!config->contains("reservation-mode")) {
return (false);
}
if (config->contains("reservations-global") ||
config->contains("reservations-in-subnet") ||
config->contains("reservations-out-of-pool")) {
isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
" one of 'reservations-global', 'reservations-in-subnet'"
" or 'reservations-out-of-pool' parameters");
}
std::string hr_mode = getString(config, "reservation-mode");
if ((hr_mode == "disabled") || (hr_mode == "off")) {
config->set("reservations-global", Element::create(false));
config->set("reservations-in-subnet", Element::create(false));
config->set("reservations-out-of-pool", Element::create(false));
} else if (hr_mode == "out-of-pool") {
config->set("reservations-global", Element::create(false));
config->set("reservations-in-subnet", Element::create(true));
config->set("reservations-out-of-pool", Element::create(true));
} else if (hr_mode == "global") {
config->set("reservations-global", Element::create(true));
config->set("reservations-in-subnet", Element::create(false));
config->set("reservations-out-of-pool", Element::create(false));
} else if (hr_mode == "all") {
config->set("reservations-global", Element::create(false));
config->set("reservations-in-subnet", Element::create(true));
config->set("reservations-out-of-pool", Element::create(false));
} else {
isc_throw(DhcpConfigError, "invalid reservation-mode parameter: '"
<< hr_mode << "' ("
<< getPosition("reservation-mode", config) << ")");
}
config->remove("reservation-mode");
return (true);
}
const Triplet<uint32_t>
BaseNetworkParser::parseLifetime(const ConstElementPtr& scope,
const std::string& name) {
@ -136,6 +173,21 @@ BaseNetworkParser::parseCommon(const ConstElementPtr& network_data,
network->setStoreExtendedInfo(getBoolean(network_data,
"store-extended-info"));
}
if (network_data->contains("reservations-global")) {
network->setReservationsGlobal(getBoolean(network_data,
"reservations-global"));
}
if (network_data->contains("reservations-in-subnet")) {
network->setReservationsInSubnet(getBoolean(network_data,
"reservations-in-subnet"));
}
if (network_data->contains("reservations-out-of-pool")) {
network->setReservationsOutOfPool(getBoolean(network_data,
"reservations-out-of-pool"));
}
}
void
@ -198,61 +250,6 @@ BaseNetworkParser::parseCacheParams(const ConstElementPtr& network_data,
}
}
void
BaseNetworkParser::parseHostReservationMode(const data::ConstElementPtr& network_data,
NetworkPtr& network) {
if (network_data->contains("reservation-mode")) {
bool found = false;
if (network_data->contains("reservations-out-of-pool") ||
network_data->contains("reservations-in-subnet") ||
network_data->contains("reservations-global")) {
found = true;
}
if (found) {
isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
" and one of 'reservations-out-of-pool'"
" , 'reservations-in-subnet' or"
" 'reservations-global' parameters");
}
try {
std::string hr_mode = getString(network_data, "reservation-mode");
network->setHostReservationMode(Network::hrModeFromString(hr_mode));
} catch (const BadValue& ex) {
isc_throw(DhcpConfigError, "invalid reservation-mode parameter: "
<< ex.what() << " (" << getPosition("reservation-mode",
network_data) << ")");
}
}
}
void
BaseNetworkParser::parseHostReservationModes(const data::ConstElementPtr& network_data,
NetworkPtr& network) {
bool found = false;
if (network_data->contains("reservations-out-of-pool") ||
network_data->contains("reservations-in-subnet") ||
network_data->contains("reservations-global")) {
found = true;
}
if (found) {
if (network_data->contains("reservation-mode")) {
isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
" and one of 'reservations-out-of-pool'"
" , 'reservations-in-subnet' or"
" 'reservations-global' parameters");
}
} else {
return;
}
try {
HostReservationModesParser parser;
Network::HRMode flags = parser.parse(network_data);
network->setHostReservationMode(flags);
} catch (const BadValue& ex) {
isc_throw(DhcpConfigError, "invalid parameter: " << ex.what());
}
}
void
BaseNetworkParser::parseDdnsParams(const data::ConstElementPtr& network_data,
NetworkPtr& network) {

View File

@ -17,6 +17,19 @@ namespace dhcp {
/// @brief Common configuration parser for shared networks
/// and subnets.
class BaseNetworkParser : public data::SimpleParser {
public:
/// @brief Moves deprecated reservation-mode parameter to
/// new reservations flags.
///
/// @param config [in/out] configuration to alter.
/// @throw DhcpConfigError on error e.g. when both reservation-mode
/// and a flag are specified.
/// @return true if reservation-mode parameter has been replaces with
/// new reservations-global, reservations-in-subnet and
/// reservations-out-of-pool parameters, false otherwise.
static bool moveReservationMode(isc::data::ElementPtr config);
protected:
/// @brief Parses DHCP lifetime.
@ -37,6 +50,9 @@ protected:
/// - rebind-timer,
/// - valid-lifetime,
/// - store-extended-info
/// - reservations-global
/// - reservations-in-subnet
/// - reservations-out-of-pool
///
/// @param network_data Data element holding shared network
/// configuration to be parsed.
@ -78,28 +94,6 @@ protected:
void parseCacheParams(const data::ConstElementPtr& network_data,
NetworkPtr& network);
/// @brief Parses host reservation mode.
///
/// @note Configuring 'reservation-mode' is deprecated. The new
/// 'reservations-out-of-pool', 'reservations-in-subnet' and
/// 'reservations-global' parameters should be used.
///
/// @param network_data Data element holding shared network
/// configuration to be parsed.
/// @param [out] network Pointer to a network in which parsed data is
/// to be stored.
void parseHostReservationMode(const data::ConstElementPtr& network_data,
NetworkPtr& network);
/// @brief Parses host reservation modes.
///
/// @param network_data Data element holding shared network
/// configuration to be parsed.
/// @param [out] network Pointer to a network in which parsed data is
/// to be stored.
void parseHostReservationModes(const data::ConstElementPtr& network_data,
NetworkPtr& network);
/// @brief Parses parameters pertaining to DDNS behavior.
///
/// The parsed parameters are:

View File

@ -743,9 +743,14 @@ Subnet4ConfigParser::initSubnet(data::ConstElementPtr params,
subnet_id));
subnet_ = subnet4;
// Move from reservation mode to new reservations flags.
ElementPtr mutable_params;
mutable_params = boost::const_pointer_cast<Element>(params);
BaseNetworkParser::moveReservationMode(mutable_params);
// Parse parameters common to all Network derivations.
NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet4);
parseCommon(params, network);
parseCommon(mutable_params, network);
std::ostringstream output;
output << addr << "/" << static_cast<int>(len) << " with params: ";
@ -859,13 +864,6 @@ Subnet4ConfigParser::initSubnet(data::ConstElementPtr params,
}
}
// reservation modes
parseHostReservationModes(params, network);
// Let's set host reservation mode. If not specified, the default value of
// all will be used.
parseHostReservationMode(params, network);
// Try setting up client class.
if (params->contains("client-class")) {
string client_class = getString(params, "client-class");
@ -1241,9 +1239,14 @@ Subnet6ConfigParser::initSubnet(data::ConstElementPtr params,
subnet_id);
subnet_.reset(subnet6);
// Move from reservation mode to new reservations flags.
ElementPtr mutable_params;
mutable_params = boost::const_pointer_cast<Element>(params);
BaseNetworkParser::moveReservationMode(mutable_params);
// Parse parameters common to all Network derivations.
NetworkPtr network = boost::dynamic_pointer_cast<Network>(subnet_);
parseCommon(params, network);
parseCommon(mutable_params, network);
// Enable or disable Rapid Commit option support for the subnet.
if (!rapid_commit.unspecified()) {
@ -1334,13 +1337,6 @@ Subnet6ConfigParser::initSubnet(data::ConstElementPtr params,
subnet6->setIface(iface);
}
// reservation modes
parseHostReservationModes(params, network);
// Let's set host reservation mode. If not specified, the default value of
// all will be used.
parseHostReservationMode(params, network);
// Try setting up client class.
if (params->contains("client-class")) {
string client_class = getString(params, "client-class");

View File

@ -44,9 +44,14 @@ SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data) {
std::string name = getString(shared_network_data, "name");
shared_network.reset(new SharedNetwork4(name));
// Move from reservation mode to new reservations flags.
ElementPtr mutable_params;
mutable_params = boost::const_pointer_cast<Element>(shared_network_data);
BaseNetworkParser::moveReservationMode(mutable_params);
// Parse parameters common to all Network derivations.
NetworkPtr network = boost::dynamic_pointer_cast<Network>(shared_network);
parseCommon(shared_network_data, network);
parseCommon(mutable_params, network);
// interface is an optional parameter
if (shared_network_data->contains("interface")) {
@ -185,12 +190,6 @@ SharedNetwork4Parser::parse(const data::ConstElementPtr& shared_network_data) {
}
}
// reservation modes
parseHostReservationModes(shared_network_data, network);
// reservation-mode
parseHostReservationMode(shared_network_data, network);
parseTeePercents(shared_network_data, network);
// Parse DDNS parameters
@ -234,9 +233,14 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) {
std::string name = getString(shared_network_data, "name");
shared_network.reset(new SharedNetwork6(name));
// Move from reservation mode to new reservations flags.
ElementPtr mutable_params;
mutable_params = boost::const_pointer_cast<Element>(shared_network_data);
BaseNetworkParser::moveReservationMode(mutable_params);
// Parse parameters common to all Network derivations.
NetworkPtr network = boost::dynamic_pointer_cast<Network>(shared_network);
parseCommon(shared_network_data, network);
parseCommon(mutable_params, network);
// preferred-lifetime
shared_network->setPreferred(parseLifetime(shared_network_data,
@ -354,12 +358,6 @@ SharedNetwork6Parser::parse(const data::ConstElementPtr& shared_network_data) {
}
}
// reservation modes
parseHostReservationModes(shared_network_data, network);
// reservation-mode
parseHostReservationMode(shared_network_data, network);
parseTeePercents(shared_network_data, network);
// Parse DDNS parameters

View File

@ -2905,6 +2905,7 @@ TEST_F(AllocEngine4Test, findReservation) {
EXPECT_FALSE(ctx.currentHost());
// Check the out of the pool reservation mode.
subnet_->setReservationsInSubnet(true);
subnet_->setReservationsOutOfPool(true);
ASSERT_NO_THROW(engine.findReservation(ctx));
EXPECT_TRUE(ctx.currentHost());

View File

@ -3719,6 +3719,7 @@ TEST_F(AllocEngine6Test, mixedHostReservedAddress) {
subnet_->setReservationsGlobal(true);
subnet_->setReservationsInSubnet(true);
subnet_->setReservationsOutOfPool(false);
// Create context which will be used to try to allocate leases
Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));
@ -3862,6 +3863,7 @@ TEST_F(AllocEngine6Test, bothHostReservedAddress) {
subnet_->setReservationsGlobal(true);
subnet_->setReservationsInSubnet(true);
subnet_->setReservationsOutOfPool(false);
// Create context which will be used to try to allocate leases
Pkt6Ptr query(new Pkt6(DHCPV6_REQUEST, 1234));

View File

@ -6,9 +6,12 @@
#include <config.h>
#include <asiolink/io_address.h>
#include <cc/data.h>
#include <dhcp/dhcp6.h>
#include <dhcp/option.h>
#include <dhcpsrv/network.h>
#include <dhcpsrv/parsers/base_network_parser.h>
#include <testutils/gtest_utils.h>
#include <boost/shared_ptr.hpp>
#include <functional>
#include <gtest/gtest.h>
@ -17,6 +20,7 @@ using namespace isc::asiolink;
using namespace isc::data;
using namespace isc::dhcp;
using namespace isc::util;
using namespace isc::test;
namespace {
@ -586,4 +590,155 @@ TEST_F(NetworkTest, getSiaddrNeverFail) {
EXPECT_NO_THROW(net4_child->getSiaddr());
}
/// @brief Test fixture class for testing @c moveReservationMode.
class NetworkReservationTest : public ::testing::Test {
public:
/// @brief Move test error case.
///
/// Error cases of @ref BaseNetworkParser::moveReservationMode.
///
/// @param config String with the config to test.
/// @param expected String with the expected error message.
void TestError(const std::string& config, const std::string& expected) {
ElementPtr cfg;
ASSERT_NO_THROW(cfg = Element::fromJSON(config))
<< "bad config, test broken";
ElementPtr copy = isc::data::copy(cfg);
EXPECT_THROW_MSG(BaseNetworkParser::moveReservationMode(cfg),
DhcpConfigError, expected);
ASSERT_TRUE(copy->equals(*cfg));
}
/// @brief Move test case.
///
/// Test cases of @ref BaseNetworkParser::moveReservationMode.
///
/// @param config String with the config to test.
/// @param expected String with the config after move.
void TestMove(const std::string& config, const std::string& expected) {
ElementPtr cfg;
ASSERT_NO_THROW(cfg = Element::fromJSON(config))
<< "bad config, test broken";
EXPECT_NO_THROW(BaseNetworkParser::moveReservationMode(cfg));
EXPECT_EQ(expected, cfg->str());
}
};
/// @brief Test @ref BaseNetworkParser::moveReservationMode error cases.
TEST_F(NetworkReservationTest, errors) {
// Conflicts.
std::string config = "{\n"
"\"reservation-mode\": \"all\",\n"
"\"reservations-global\": true\n"
"}";
std::string expected = "invalid use of both 'reservation-mode'"
" one of 'reservations-global', 'reservations-in-subnet'"
" or 'reservations-out-of-pool' parameters";
TestError(config, expected);
config = "{\n"
"\"reservation-mode\": \"all\",\n"
"\"reservations-in-subnet\": true\n"
"}";
TestError(config, expected);
config = "{\n"
"\"reservation-mode\": \"all\",\n"
"\"reservations-out-of-pool\": false\n"
"}";
TestError(config, expected);
// Unknown mode.
config = "{\n"
"\"reservation-mode\": \"foo\"\n"
"}";
expected = "invalid reservation-mode parameter: 'foo' (<string>:2:21)";
TestError(config, expected);
}
/// @brief Test @ref BaseNetworkParser::moveReservationMode.
TEST_F(NetworkReservationTest, move) {
// No-ops.
std::string config = "{\n"
"}";
std::string expected = "{ "
" }";
TestMove(config, expected);
config = "{\n"
"\"reservations-global\": true\n"
"}";
expected = "{"
" \"reservations-global\": true"
" }";
TestMove(config, expected);
// Disabled.
config = "{\n"
"\"reservation-mode\": \"disabled\"\n"
"}";
expected = "{"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": false,"
" \"reservations-out-of-pool\": false"
" }";
TestMove(config, expected);
config = "{\n"
"\"reservation-mode\": \"off\"\n"
"}";
TestMove(config, expected);
// Out-of-pool.
config = "{\n"
"\"reservation-mode\": \"out-of-pool\"\n"
"}";
expected = "{"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": true"
" }";
TestMove(config, expected);
// Global.
config = "{\n"
"\"reservation-mode\": \"global\"\n"
"}";
expected = "{"
" \"reservations-global\": true,"
" \"reservations-in-subnet\": false,"
" \"reservations-out-of-pool\": false"
" }";
TestMove(config, expected);
// All.
config = "{\n"
"\"reservation-mode\": \"all\"\n"
"}";
expected = "{"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": false"
" }";
TestMove(config, expected);
config = "{\n"
"\"foobar\": 1234,\n"
"\"reservation-mode\": \"all\"\n"
"}";
expected = "{"
" \"foobar\": 1234,"
" \"reservations-global\": false,"
" \"reservations-in-subnet\": true,"
" \"reservations-out-of-pool\": false"
" }";
TestMove(config, expected);
}
}