mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 05:27:55 +00:00
[5357] Addressed comments after review:
- many more parameters are now inherited from shared-network to subnet4 - parameters now passed as const reference - it is no longer possible to specify echo-client-id on shared-network level (because it's a global parameter) - example config commented properly
This commit is contained in:
parent
de94f82ba0
commit
3e1e56f151
@ -1,38 +1,84 @@
|
||||
|
||||
// This is an example configuration file for DHCPv4 server in Kea.
|
||||
// It demonstrates an advanced feature called shared network. Typically, for
|
||||
// each physical link there is one IPv4 subnet that the server is expected
|
||||
// to manage. However, in some cases there is a need to configure more subnets
|
||||
// in the same physical location. The most common use case is an existing
|
||||
// subnet that grew past its original assumptions and ran out of addresses,
|
||||
// so the sysadmin needs to add another subnet on top of existing one.
|
||||
{
|
||||
"Dhcp4": {
|
||||
|
||||
// As with any other configuration, you need to tell Kea the interface
|
||||
// names, so it would listen to incoming traffic.
|
||||
"interfaces-config": {
|
||||
"interfaces": [ "eth0" ]
|
||||
},
|
||||
|
||||
// You also need to tell where to store lease information.
|
||||
// memfile is the backend that is easiest to set up.
|
||||
"lease-database": {
|
||||
"type": "memfile",
|
||||
"lfc-interval": 3600
|
||||
},
|
||||
|
||||
// Here the shared networks definition starts. shared-networks can
|
||||
// contain a list of shared networks. There are many parameters
|
||||
// that can be specfied here, so this example may be overwhelming
|
||||
// at first, but the only mandatory parameter for each shared
|
||||
// network is name. It must be unique. Typically, each shared
|
||||
// subnet also needs to have at least two subnets to be functional,
|
||||
// but if you really want to, you can define a degraded shared
|
||||
// network that has 1 or even 0 subnets. This may come in handy
|
||||
// when migrating between regular subnets and shared networks
|
||||
// or when debugging a problem. It is not recommended to use
|
||||
// 1 subnet per shared network, as there is extra processing
|
||||
// overhead for shared networks.
|
||||
"shared-networks": [
|
||||
{
|
||||
"interface": "eth1",
|
||||
"match-client-id": false,
|
||||
// Name of the shared network. It may be an arbitrary string
|
||||
// and it must be unique among all shared networks.
|
||||
"name": "frog",
|
||||
|
||||
// You may specify interface name if the shared network is
|
||||
// reachable directly from the server.
|
||||
"interface": "eth1",
|
||||
|
||||
// You can specify many parameters that are allowed in subnet scope
|
||||
// here. It's useful to put them here if they apply to all subnets
|
||||
// in this shared network. It's likely that the most common
|
||||
// parameter here will be option values defined with option-data.
|
||||
"match-client-id": false,
|
||||
"option-data": [ ],
|
||||
"rebind-timer": 150,
|
||||
|
||||
// If all the traffic coming from that shared subnet is reachable
|
||||
// via relay and that relay always use the same IP address, you
|
||||
// can specify that relay address here. Since this example shows
|
||||
// a shared network reachable directly, we put 0.0.0.0 here.
|
||||
// It would be better to skip the relay scope altogether, but
|
||||
// it was left here for demonstration purposes.
|
||||
"relay": {
|
||||
"ip-address": "0.0.0.0"
|
||||
},
|
||||
|
||||
// Timer values can be overridden here.
|
||||
"renew-timer": 100,
|
||||
"reservation-mode": "all",
|
||||
|
||||
// This starts a list of subnets allowed in this shared network.
|
||||
// In our example, there are two subnets.
|
||||
"subnet4": [
|
||||
{
|
||||
"4o6-interface": "",
|
||||
"4o6-interface-id": "",
|
||||
"4o6-subnet": "",
|
||||
"id": 1,
|
||||
"match-client-id": true,
|
||||
"next-server": "0.0.0.0",
|
||||
"option-data": [ ],
|
||||
"pools": [ ],
|
||||
"rebind-timer": 20,
|
||||
|
||||
// You can override the value inherited from shared-network
|
||||
// here if your relay uses different IP addresses for
|
||||
// each subnet.
|
||||
"relay": {
|
||||
"ip-address": "0.0.0.0"
|
||||
},
|
||||
@ -42,18 +88,12 @@
|
||||
"valid-lifetime": 30
|
||||
},
|
||||
{
|
||||
"4o6-interface": "",
|
||||
"4o6-interface-id": "",
|
||||
"4o6-subnet": "",
|
||||
"id": 2,
|
||||
"match-client-id": true,
|
||||
"next-server": "0.0.0.0",
|
||||
"option-data": [ ],
|
||||
"pools": [ ],
|
||||
"rebind-timer": 20,
|
||||
"relay": {
|
||||
"ip-address": "0.0.0.0"
|
||||
},
|
||||
"renew-timer": 10,
|
||||
"reservation-mode": "all",
|
||||
"subnet": "192.0.2.0/24",
|
||||
@ -63,6 +103,10 @@
|
||||
"valid-lifetime": 200
|
||||
} ], // end of shared-networks
|
||||
|
||||
// It is likely that in your network you'll have a mix or regular,
|
||||
// "plain" subnets and shared networks. It is perfectly valid to mix
|
||||
// them in the same config file.
|
||||
//
|
||||
// This is regular subnet. It's not part of any shared-network.
|
||||
"subnet4": [
|
||||
{
|
||||
@ -72,6 +116,6 @@
|
||||
"id": 3
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
} // end of Dhcp4
|
||||
}
|
||||
|
@ -1002,7 +1002,6 @@ shared_network_param: name
|
||||
| next_server
|
||||
| relay
|
||||
| reservation_mode
|
||||
| echo_client_id
|
||||
| client_classes
|
||||
| valid_lifetime
|
||||
| unknown_map_entry
|
||||
|
@ -72,7 +72,7 @@ public:
|
||||
///
|
||||
/// @throw DhcpConfigError if parameters are missing or
|
||||
/// or having incorrect values.
|
||||
void parse(SrvConfigPtr cfg, ConstElementPtr global) {
|
||||
void parse(const SrvConfigPtr& cfg, const ConstElementPtr& global) {
|
||||
|
||||
// Set whether v4 server is supposed to echo back client-id
|
||||
// (yes = RFC6842 compatible, no = backward compatibility)
|
||||
@ -96,7 +96,7 @@ public:
|
||||
/// @throw BadValue if any pointer is missing
|
||||
/// @throw DhcpConfigError if there are duplicates (or other subnet defects)
|
||||
void
|
||||
copySubnets4(const CfgSubnets4Ptr dest, const CfgSharedNetworks4Ptr from) {
|
||||
copySubnets4(const CfgSubnets4Ptr& dest, const CfgSharedNetworks4Ptr& from) {
|
||||
|
||||
if (!dest || !from) {
|
||||
isc_throw(BadValue, "Unable to copy subnets: at least one pointer is null");
|
||||
@ -136,7 +136,7 @@ public:
|
||||
/// @param global global Dhcp4 scope
|
||||
/// @throw DhcpConfigError in case of issues found
|
||||
void
|
||||
sanityChecks(SrvConfigPtr cfg, ConstElementPtr global) {
|
||||
sanityChecks(const SrvConfigPtr& cfg, const ConstElementPtr& global) {
|
||||
|
||||
/// Shared network sanity checks
|
||||
const SharedNetwork4Collection* networks = cfg->getCfgSharedNetworks4()->getAll();
|
||||
|
@ -611,17 +611,23 @@ public:
|
||||
/// @param t1 expected renew-timer value
|
||||
/// @param t2 expected rebind-timer value
|
||||
/// @param valid expected valid-lifetime value
|
||||
void
|
||||
/// @return the subnet that was examined
|
||||
Subnet4Ptr
|
||||
checkSubnet(const Subnet4Collection& col, std::string subnet,
|
||||
uint32_t t1, uint32_t t2, uint32_t valid) {
|
||||
const auto& index = col.get<SubnetPrefixIndexTag>();
|
||||
auto subnet_it = index.find(subnet);
|
||||
ASSERT_NE(subnet_it, index.cend());
|
||||
if (subnet_it == index.cend()) {
|
||||
ADD_FAILURE() << "Unable to find expected subnet " << subnet;
|
||||
return (Subnet4Ptr());
|
||||
}
|
||||
Subnet4Ptr s = *subnet_it;
|
||||
|
||||
EXPECT_EQ(t1, s->getT1());
|
||||
EXPECT_EQ(t2, s->getT2());
|
||||
EXPECT_EQ(valid, s->getValid());
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
/// @brief This utility method attempts to configure using specified
|
||||
@ -5209,13 +5215,34 @@ TEST_F(Dhcp4ParserTest, sharedNetworks3subnets) {
|
||||
// - shared network to subnet
|
||||
// Also, it tests that more than one shared network can be defined.
|
||||
TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
|
||||
|
||||
// We need to fake the interfaces present, because we want to test
|
||||
// interface names inheritance. However, there are sanity checks
|
||||
// on subnet level that would refuse the value if the interface
|
||||
// is not present.
|
||||
IfaceMgrTestConfig iface_config(true);
|
||||
|
||||
// This config is structured in a way that the first shared
|
||||
// subnet have many parameters defined. The first subnet
|
||||
// should inherit them. The second subnet overrides all
|
||||
// values and those values should be used, not those from
|
||||
// shared network scope.
|
||||
string config = "{\n"
|
||||
"\"renew-timer\": 1, \n"
|
||||
"\"renew-timer\": 1, \n" // global values here
|
||||
"\"rebind-timer\": 2, \n"
|
||||
"\"valid-lifetime\": 4, \n"
|
||||
"\"shared-networks\": [ {\n"
|
||||
" \"name\": \"foo\"\n,"
|
||||
" \"name\": \"foo\"\n," // shared network values here
|
||||
" \"interface\": \"eth0\",\n"
|
||||
" \"match-client-id\": false,\n"
|
||||
" \"next-server\": \"1.2.3.4\",\n"
|
||||
" \"relay\": {\n"
|
||||
" \"ip-address\": \"5.6.7.8\"\n"
|
||||
" },\n"
|
||||
" \"reservation-mode\": \"out-of-pool\",\n"
|
||||
" \"renew-timer\": 10,\n"
|
||||
" \"rebind-timer\": 20,\n"
|
||||
" \"valid-lifetime\": 40,\n"
|
||||
" \"subnet4\": [\n"
|
||||
" { \n"
|
||||
" \"subnet\": \"192.0.1.0/24\",\n"
|
||||
@ -5224,10 +5251,17 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
|
||||
" { \n"
|
||||
" \"subnet\": \"192.0.2.0/24\",\n"
|
||||
" \"pools\": [ { \"pool\": \"192.0.2.1-192.0.2.10\" } ],\n"
|
||||
" \"renew-timer\": 100\n"
|
||||
" \"renew-timer\": 100,\n"
|
||||
" \"rebind-timer\": 200,\n"
|
||||
" \"valid-lifetime\": 400,\n"
|
||||
" \"match-client-id\": true,\n"
|
||||
" \"next-server\": \"11.22.33.44\",\n"
|
||||
" \"relay\": {\n"
|
||||
" \"ip-address\": \"55.66.77.88\"\n"
|
||||
" },\n"
|
||||
" \"reservation-mode\": \"disabled\"\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
|
||||
" },\n"
|
||||
"{ // second shared-network starts here\n"
|
||||
" \"name\": \"bar\",\n"
|
||||
@ -5265,13 +5299,28 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
|
||||
// derived from shared-network level. Other parameters a derived
|
||||
// from global scope to shared-network level and later again to
|
||||
// subnet4 level.
|
||||
checkSubnet(*subs, "192.0.1.0/24", 10, 2, 4);
|
||||
Subnet4Ptr s = checkSubnet(*subs, "192.0.1.0/24", 10, 20, 40);
|
||||
ASSERT_TRUE(s);
|
||||
|
||||
// These are values derived from shared network scope:
|
||||
EXPECT_EQ("eth0", s->getIface());
|
||||
EXPECT_EQ(false, s->getMatchClientId());
|
||||
EXPECT_EQ(IOAddress("1.2.3.4"), s->getSiaddr());
|
||||
EXPECT_EQ(IOAddress("5.6.7.8"), s->getRelayInfo().addr_);
|
||||
EXPECT_EQ(Network::HR_OUT_OF_POOL, s->getHostReservationMode());
|
||||
|
||||
// For the second subnet, the renew-timer should be 100, because it
|
||||
// was specified explicitly. Other parameters a derived
|
||||
// from global scope to shared-network level and later again to
|
||||
// subnet4 level.
|
||||
checkSubnet(*subs, "192.0.2.0/24", 100, 2, 4);
|
||||
s = checkSubnet(*subs, "192.0.2.0/24", 100, 200, 400);
|
||||
|
||||
// These are values derived from shared network scope:
|
||||
EXPECT_EQ("eth0", s->getIface());
|
||||
EXPECT_EQ(true, s->getMatchClientId());
|
||||
EXPECT_EQ(IOAddress("11.22.33.44"), s->getSiaddr());
|
||||
EXPECT_EQ(IOAddress("55.66.77.88"), s->getRelayInfo().addr_);
|
||||
EXPECT_EQ(Network::HR_DISABLED, s->getHostReservationMode());
|
||||
|
||||
// Ok, now check the second shared subnet.
|
||||
net = nets->at(1);
|
||||
@ -5282,9 +5331,13 @@ TEST_F(Dhcp4ParserTest, sharedNetworksDerive) {
|
||||
EXPECT_EQ(1, subs->size());
|
||||
|
||||
// This subnet should derive its renew-timer from global scope.
|
||||
checkSubnet(*subs, "192.0.3.0/24", 1, 2, 4);
|
||||
|
||||
// All other parameters should have default values.
|
||||
s = checkSubnet(*subs, "192.0.3.0/24", 1, 2, 4);
|
||||
EXPECT_EQ("", s->getIface());
|
||||
EXPECT_EQ(true, s->getMatchClientId());
|
||||
EXPECT_EQ(IOAddress("0.0.0.0"), s->getSiaddr());
|
||||
EXPECT_EQ(IOAddress("0.0.0.0"), s->getRelayInfo().addr_);
|
||||
EXPECT_EQ(Network::HR_ALL, s->getHostReservationMode());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -982,6 +982,7 @@ shared_network_params: shared_network_param
|
||||
shared_network_param: name
|
||||
| subnet6_list
|
||||
| interface
|
||||
| interface_id
|
||||
| renew_timer
|
||||
| rebind_timer
|
||||
| option_data_list
|
||||
|
@ -322,18 +322,24 @@ public:
|
||||
/// @param t2 expected rebind-timer value
|
||||
/// @param preferred expected preferred-lifetime value
|
||||
/// @param valid expected valid-lifetime value
|
||||
void
|
||||
/// @return the subnet that was examined
|
||||
Subnet6Ptr
|
||||
checkSubnet(const Subnet6Collection& col, std::string subnet,
|
||||
uint32_t t1, uint32_t t2, uint32_t pref, uint32_t valid) {
|
||||
const auto& index = col.get<SubnetPrefixIndexTag>();
|
||||
auto subnet_it = index.find(subnet);
|
||||
ASSERT_NE(subnet_it, index.cend());
|
||||
if (subnet_it == index.cend()) {
|
||||
ADD_FAILURE() << "Unable to find expected subnet " << subnet;
|
||||
return (Subnet6Ptr());
|
||||
}
|
||||
Subnet6Ptr s = *subnet_it;
|
||||
|
||||
EXPECT_EQ(t1, s->getT1());
|
||||
EXPECT_EQ(t2, s->getT2());
|
||||
EXPECT_EQ(pref, s->getPreferred());
|
||||
EXPECT_EQ(valid, s->getValid());
|
||||
|
||||
return (s);
|
||||
}
|
||||
|
||||
/// @brief Returns an interface configuration used by the most of the
|
||||
@ -863,7 +869,7 @@ TEST_F(Dhcp6ParserTest, emptySubnet) {
|
||||
|
||||
ConstElementPtr status;
|
||||
EXPECT_NO_THROW(status = configureDhcp6Server(srv_, json));
|
||||
|
||||
|
||||
|
||||
// returned value should be 0 (success)
|
||||
checkResult(status, 0);
|
||||
@ -5558,6 +5564,21 @@ TEST_F(Dhcp6ParserTest, sharedNetworks3subnets) {
|
||||
// - shared network to subnet
|
||||
// Also, it tests that more than one shared network can be defined.
|
||||
TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
|
||||
|
||||
// We need to fake the interfaces present, because we want to test
|
||||
// interface names inheritance. However, there are sanity checks
|
||||
// on subnet level that would refuse the value if the interface
|
||||
// is not present.
|
||||
IfaceMgrTestConfig iface_config(true);
|
||||
|
||||
// Build some expected interface-id values.
|
||||
const string text1 = "oneone";
|
||||
const string text2 = "twotwo";
|
||||
OptionBuffer buffer1 = OptionBuffer(text1.begin(), text1.end());
|
||||
OptionBuffer buffer2 = OptionBuffer(text2.begin(), text2.end());
|
||||
Option iface_id1(Option::V6, D6O_INTERFACE_ID, buffer1);
|
||||
Option iface_id2(Option::V6, D6O_INTERFACE_ID, buffer2);
|
||||
|
||||
string config = "{\n"
|
||||
"\"renew-timer\": 1, \n"
|
||||
"\"rebind-timer\": 2, \n"
|
||||
@ -5566,6 +5587,15 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
|
||||
"\"shared-networks\": [ {\n"
|
||||
" \"name\": \"foo\"\n,"
|
||||
" \"renew-timer\": 10,\n"
|
||||
" \"rebind-timer\": 20, \n"
|
||||
" \"preferred-lifetime\": 30,\n"
|
||||
" \"valid-lifetime\": 40, \n"
|
||||
" \"interface-id\": \"oneone\",\n"
|
||||
" \"relay\": {\n"
|
||||
" \"ip-address\": \"1111::1\"\n"
|
||||
" },\n"
|
||||
" \"rapid-commit\": true,\n"
|
||||
" \"reservation-mode\": \"disabled\",\n"
|
||||
" \"subnet6\": [\n"
|
||||
" { \n"
|
||||
" \"subnet\": \"2001:db1::/48\",\n"
|
||||
@ -5574,7 +5604,16 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
|
||||
" { \n"
|
||||
" \"subnet\": \"2001:db2::/48\",\n"
|
||||
" \"pools\": [ { \"pool\": \"2001:db2::/64\" } ],\n"
|
||||
" \"renew-timer\": 100\n"
|
||||
" \"renew-timer\": 100\n,"
|
||||
" \"rebind-timer\": 200, \n"
|
||||
" \"preferred-lifetime\": 300,\n"
|
||||
" \"relay\": {\n"
|
||||
" \"ip-address\": \"2222::2\"\n"
|
||||
" },\n"
|
||||
" \"valid-lifetime\": 400, \n"
|
||||
" \"interface-id\": \"twotwo\",\n"
|
||||
" \"rapid-commit\": false,\n"
|
||||
" \"reservation-mode\": \"out-of-pool\"\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" },\n"
|
||||
@ -5613,13 +5652,24 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
|
||||
// derived from shared-network level. Other parameters a derived
|
||||
// from global scope to shared-network level and later again to
|
||||
// subnet6 level.
|
||||
checkSubnet(*subs, "2001:db1::/48", 10, 2, 3, 4);
|
||||
Subnet6Ptr s = checkSubnet(*subs, "2001:db1::/48", 10, 20, 30, 40);
|
||||
ASSERT_TRUE(s);
|
||||
ASSERT_TRUE(s->getInterfaceId());
|
||||
EXPECT_TRUE(iface_id1.equals(s->getInterfaceId()));
|
||||
EXPECT_EQ(IOAddress("1111::1"), s->getRelayInfo().addr_);
|
||||
EXPECT_EQ(true, s->getRapidCommit());
|
||||
EXPECT_EQ(Network::HR_DISABLED, s->getHostReservationMode());
|
||||
|
||||
// For the second subnet, the renew-timer should be 100, because it
|
||||
// was specified explicitly. Other parameters a derived
|
||||
// from global scope to shared-network level and later again to
|
||||
// subnet6 level.
|
||||
checkSubnet(*subs, "2001:db2::/48", 100, 2, 3, 4);
|
||||
s = checkSubnet(*subs, "2001:db2::/48", 100, 200, 300, 400);
|
||||
ASSERT_TRUE(s->getInterfaceId());
|
||||
EXPECT_TRUE(iface_id2.equals(s->getInterfaceId()));
|
||||
EXPECT_EQ(IOAddress("2222::2"), s->getRelayInfo().addr_);
|
||||
EXPECT_EQ(false, s->getRapidCommit());
|
||||
EXPECT_EQ(Network::HR_OUT_OF_POOL, s->getHostReservationMode());
|
||||
|
||||
// Ok, now check the second shared subnet.
|
||||
net = nets->at(1);
|
||||
@ -5630,7 +5680,97 @@ TEST_F(Dhcp6ParserTest, sharedNetworksDerive) {
|
||||
EXPECT_EQ(1, subs->size());
|
||||
|
||||
// This subnet should derive its renew-timer from global scope.
|
||||
checkSubnet(*subs, "2001:db3::/48", 1, 2, 3, 4);
|
||||
s = checkSubnet(*subs, "2001:db3::/48", 1, 2, 3, 4);
|
||||
EXPECT_FALSE(s->getInterfaceId());
|
||||
EXPECT_EQ(IOAddress("::"), s->getRelayInfo().addr_);
|
||||
EXPECT_EQ(false, s->getRapidCommit());
|
||||
EXPECT_EQ(Network::HR_ALL, s->getHostReservationMode());
|
||||
}
|
||||
|
||||
// Since it is not allowed to define both interface-id and interface
|
||||
// for the same subnet, we need dedicated test that will check
|
||||
// interface separately.
|
||||
TEST_F(Dhcp6ParserTest, sharedNetworksDeriveInterfaces) {
|
||||
|
||||
// We need to fake the interfaces present, because we want to test
|
||||
// interface names inheritance. However, there are sanity checks
|
||||
// on subnet level that would refuse the value if the interface
|
||||
// is not present.
|
||||
IfaceMgrTestConfig iface_config(true);
|
||||
|
||||
string config = "{\n"
|
||||
"\"shared-networks\": [ {\n"
|
||||
" \"name\": \"foo\"\n,"
|
||||
" \"interface\": \"eth0\",\n"
|
||||
" \"subnet6\": [\n"
|
||||
" { \n"
|
||||
" \"subnet\": \"2001:db1::/48\",\n"
|
||||
" \"pools\": [ { \"pool\": \"2001:db1::/64\" } ]\n"
|
||||
" },\n"
|
||||
" { \n"
|
||||
" \"subnet\": \"2001:db2::/48\",\n"
|
||||
" \"pools\": [ { \"pool\": \"2001:db2::/64\" } ],\n"
|
||||
" \"interface\": \"eth0\"\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
" },\n"
|
||||
"{ // second shared-network starts here\n"
|
||||
" \"name\": \"bar\",\n"
|
||||
" \"subnet6\": [\n"
|
||||
" {\n"
|
||||
" \"subnet\": \"2001:db3::/48\",\n"
|
||||
" \"pools\": [ { \"pool\": \"2001:db3::/64\" } ]\n"
|
||||
" }\n"
|
||||
" ]\n"
|
||||
"} ]\n"
|
||||
"} \n";
|
||||
|
||||
configure(config, CONTROL_RESULT_SUCCESS, "");
|
||||
|
||||
// Now verify that the shared network was indeed configured.
|
||||
CfgSharedNetworks6Ptr cfg_net = CfgMgr::instance().getStagingCfg()
|
||||
->getCfgSharedNetworks6();
|
||||
|
||||
// Two shared networks are expeced.
|
||||
ASSERT_TRUE(cfg_net);
|
||||
const SharedNetwork6Collection* nets = cfg_net->getAll();
|
||||
ASSERT_TRUE(nets);
|
||||
ASSERT_EQ(2, nets->size());
|
||||
|
||||
// Let's check the first one.
|
||||
SharedNetwork6Ptr net = nets->at(0);
|
||||
ASSERT_TRUE(net);
|
||||
|
||||
const Subnet6Collection * subs = net->getAllSubnets();
|
||||
ASSERT_TRUE(subs);
|
||||
EXPECT_EQ(2, subs->size());
|
||||
|
||||
// For the first subnet, the renew-timer should be 10, because it was
|
||||
// derived from shared-network level. Other parameters a derived
|
||||
// from global scope to shared-network level and later again to
|
||||
// subnet6 level.
|
||||
Subnet6Ptr s = checkSubnet(*subs, "2001:db1::/48", 900, 1800, 3600, 7200);
|
||||
ASSERT_TRUE(s);
|
||||
EXPECT_EQ("eth0", s->getIface());
|
||||
|
||||
// For the second subnet, the renew-timer should be 100, because it
|
||||
// was specified explicitly. Other parameters a derived
|
||||
// from global scope to shared-network level and later again to
|
||||
// subnet6 level.
|
||||
checkSubnet(*subs, "2001:db2::/48", 900, 1800, 3600, 7200);
|
||||
EXPECT_EQ("eth0", s->getIface());
|
||||
|
||||
// Ok, now check the second shared subnet.
|
||||
net = nets->at(1);
|
||||
ASSERT_TRUE(net);
|
||||
|
||||
subs = net->getAllSubnets();
|
||||
ASSERT_TRUE(subs);
|
||||
EXPECT_EQ(1, subs->size());
|
||||
|
||||
// This subnet should derive its renew-timer from global scope.
|
||||
s = checkSubnet(*subs, "2001:db3::/48", 900, 1800, 3600, 7200);
|
||||
EXPECT_EQ("", s->getIface());
|
||||
}
|
||||
|
||||
};
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <dhcpsrv/parsers/simple_parser4.h>
|
||||
#include <cc/data.h>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <iostream>
|
||||
|
||||
using namespace isc::data;
|
||||
|
||||
@ -66,6 +67,12 @@ const SimpleDefaults SimpleParser4::GLOBAL4_DEFAULTS = {
|
||||
};
|
||||
|
||||
/// @brief This table defines default values for each IPv4 subnet.
|
||||
///
|
||||
/// Note: When updating this array, please also update SHARED_SUBNET4_DEFAULTS
|
||||
/// below. In most cases, those two should be kept in sync, except cases
|
||||
/// where a parameter can be derived from shared-networks, but is not
|
||||
/// defined on global level. Currently there are two such parameters:
|
||||
/// interface and reservation-mode
|
||||
const SimpleDefaults SimpleParser4::SUBNET4_DEFAULTS = {
|
||||
{ "id", Element::integer, "0" }, // 0 means autogenerate
|
||||
{ "interface", Element::string, "" },
|
||||
@ -76,24 +83,51 @@ const SimpleDefaults SimpleParser4::SUBNET4_DEFAULTS = {
|
||||
{ "4o6-subnet", Element::string, "" },
|
||||
};
|
||||
|
||||
/// @brief This table defines default values for each IPv4 subnet that is
|
||||
/// part of a shared network
|
||||
///
|
||||
/// This is mostly the same as @ref SUBNET4_DEFAULTS, except two parameters
|
||||
/// that can be derived from shared-network, but cannot from global scope.
|
||||
/// Those are: interface and reservation-mode.
|
||||
const SimpleDefaults SimpleParser4::SHARED_SUBNET4_DEFAULTS = {
|
||||
{ "id", Element::integer, "0" }, // 0 means autogenerate
|
||||
{ "client-class", Element::string, "" },
|
||||
{ "4o6-interface", Element::string, "" },
|
||||
{ "4o6-interface-id", Element::string, "" },
|
||||
{ "4o6-subnet", Element::string, "" },
|
||||
};
|
||||
|
||||
/// @brief This table defines default values for each IPv4 shared network.
|
||||
const SimpleDefaults SimpleParser4::SHARED_NETWORK4_DEFAULTS = {
|
||||
{ "interface", Element::string, "" },
|
||||
{ "reservation-mode", Element::string, "all" }
|
||||
};
|
||||
|
||||
/// @brief This table defines default values for interfaces for DHCPv4.
|
||||
const SimpleDefaults SimpleParser4::IFACE4_DEFAULTS = {
|
||||
{ "re-detect", Element::boolean, "true" }
|
||||
};
|
||||
|
||||
/// @brief List of parameters that can be inherited from the global to subnet4 scope.
|
||||
/// @brief List of parameters that can be inherited to subnet4 scope.
|
||||
///
|
||||
/// Some parameters may be defined on both global (directly in Dhcp4) and
|
||||
/// subnet (Dhcp4/subnet4/...) scope. If not defined in the subnet scope,
|
||||
/// the value is being inherited (derived) from the global scope. This
|
||||
/// array lists all of such parameters.
|
||||
const ParamsList SimpleParser4::INHERIT_GLOBAL_TO_SUBNET4 = {
|
||||
"renew-timer",
|
||||
"rebind-timer",
|
||||
"valid-lifetime",
|
||||
///
|
||||
/// This list is also used for inheriting from global to shared networks
|
||||
/// and from shared networks to subnets within it.
|
||||
const ParamsList SimpleParser4::INHERIT_TO_SUBNET4 = {
|
||||
"interface",
|
||||
"match-client-id",
|
||||
"next-server"
|
||||
"next-server",
|
||||
"rebind-timer",
|
||||
"relay",
|
||||
"renew-timer",
|
||||
"reservation-mode",
|
||||
"valid-lifetime"
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
/// ---------------------------------------------------------------------------
|
||||
@ -137,9 +171,12 @@ size_t SimpleParser4::setAllDefaults(isc::data::ElementPtr global) {
|
||||
ConstElementPtr shared = global->get("shared-networks");
|
||||
if (shared) {
|
||||
BOOST_FOREACH(ElementPtr net, shared->listValue()) {
|
||||
|
||||
cnt += setDefaults(net, SHARED_NETWORK4_DEFAULTS);
|
||||
|
||||
ConstElementPtr subs = net->get("subnet4");
|
||||
if (subs) {
|
||||
cnt += setListDefaults(subs, SUBNET4_DEFAULTS);
|
||||
cnt += setListDefaults(subs, SHARED_SUBNET4_DEFAULTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -155,7 +192,7 @@ size_t SimpleParser4::deriveParameters(isc::data::ElementPtr global) {
|
||||
if (subnets) {
|
||||
BOOST_FOREACH(ElementPtr single_subnet, subnets->listValue()) {
|
||||
cnt += SimpleParser::deriveParams(global, single_subnet,
|
||||
INHERIT_GLOBAL_TO_SUBNET4);
|
||||
INHERIT_TO_SUBNET4);
|
||||
}
|
||||
}
|
||||
|
||||
@ -169,16 +206,17 @@ size_t SimpleParser4::deriveParameters(isc::data::ElementPtr global) {
|
||||
// if defined there.
|
||||
// Then try to inherit them from global.
|
||||
cnt += SimpleParser::deriveParams(global, net,
|
||||
INHERIT_GLOBAL_TO_SUBNET4);
|
||||
INHERIT_TO_SUBNET4);
|
||||
|
||||
// Now we need to go thrugh all the subnets in this net.
|
||||
subnets = net->get("subnet4");
|
||||
if (subnets) {
|
||||
BOOST_FOREACH(ElementPtr single_subnet, subnets->listValue()) {
|
||||
cnt += SimpleParser::deriveParams(net, single_subnet,
|
||||
INHERIT_GLOBAL_TO_SUBNET4);
|
||||
INHERIT_TO_SUBNET4);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,10 @@ public:
|
||||
static const isc::data::SimpleDefaults OPTION4_DEFAULTS;
|
||||
static const isc::data::SimpleDefaults GLOBAL4_DEFAULTS;
|
||||
static const isc::data::SimpleDefaults SUBNET4_DEFAULTS;
|
||||
static const isc::data::SimpleDefaults SHARED_SUBNET4_DEFAULTS;
|
||||
static const isc::data::SimpleDefaults SHARED_NETWORK4_DEFAULTS;
|
||||
static const isc::data::SimpleDefaults IFACE4_DEFAULTS;
|
||||
static const isc::data::ParamsList INHERIT_GLOBAL_TO_SUBNET4;
|
||||
static const isc::data::ParamsList INHERIT_TO_SUBNET4;
|
||||
};
|
||||
|
||||
};
|
||||
|
@ -73,6 +73,21 @@ const SimpleDefaults SimpleParser6::SUBNET6_DEFAULTS = {
|
||||
{ "interface-id", Element::string, "" },
|
||||
};
|
||||
|
||||
/// @brief This table defines default values for each IPv6 subnet.
|
||||
const SimpleDefaults SimpleParser6::SHARED_SUBNET6_DEFAULTS = {
|
||||
{ "id", Element::integer, "0" }, // 0 means autogenerate
|
||||
{ "client-class", Element::string, "" }
|
||||
};
|
||||
|
||||
/// @brief This table defines default values for each IPv6 shared network.
|
||||
const SimpleDefaults SimpleParser6::SHARED_NETWORK6_DEFAULTS = {
|
||||
{ "interface", Element::string, "" },
|
||||
{ "interface-id", Element::string, "" },
|
||||
{ "reservation-mode", Element::string, "all" },
|
||||
{ "rapid-commit", Element::boolean, "false" } // rapid-commit disabled by default
|
||||
};
|
||||
|
||||
|
||||
/// @brief This table defines default values for interfaces for DHCPv6.
|
||||
const SimpleDefaults SimpleParser6::IFACE6_DEFAULTS = {
|
||||
{ "re-detect", Element::boolean, "true" }
|
||||
@ -84,10 +99,18 @@ const SimpleDefaults SimpleParser6::IFACE6_DEFAULTS = {
|
||||
/// subnet (Dhcp6/subnet6/...) scope. If not defined in the subnet scope,
|
||||
/// the value is being inherited (derived) from the global scope. This
|
||||
/// array lists all of such parameters.
|
||||
const ParamsList SimpleParser6::INHERIT_GLOBAL_TO_SUBNET6 = {
|
||||
"renew-timer",
|
||||
"rebind-timer",
|
||||
///
|
||||
/// This list is also used for inheriting from global to shared networks
|
||||
/// and from shared networks to subnets within it.
|
||||
const ParamsList SimpleParser6::INHERIT_TO_SUBNET6 = {
|
||||
"interface",
|
||||
"interface-id",
|
||||
"preferred-lifetime",
|
||||
"rapid-commit",
|
||||
"rebind-timer",
|
||||
"relay",
|
||||
"renew-timer",
|
||||
"reservation-mode",
|
||||
"valid-lifetime"
|
||||
};
|
||||
/// @}
|
||||
@ -135,9 +158,12 @@ size_t SimpleParser6::setAllDefaults(isc::data::ElementPtr global) {
|
||||
ConstElementPtr shared = global->get("shared-networks");
|
||||
if (shared) {
|
||||
BOOST_FOREACH(ElementPtr net, shared->listValue()) {
|
||||
|
||||
cnt += setDefaults(net, SHARED_NETWORK6_DEFAULTS);
|
||||
|
||||
ConstElementPtr subs = net->get("subnet6");
|
||||
if (subs) {
|
||||
cnt += setListDefaults(subs, SUBNET6_DEFAULTS);
|
||||
cnt += setListDefaults(subs, SHARED_SUBNET6_DEFAULTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -152,7 +178,7 @@ size_t SimpleParser6::deriveParameters(isc::data::ElementPtr global) {
|
||||
if (subnets) {
|
||||
BOOST_FOREACH(ElementPtr single_subnet, subnets->listValue()) {
|
||||
cnt += SimpleParser::deriveParams(global, single_subnet,
|
||||
INHERIT_GLOBAL_TO_SUBNET6);
|
||||
INHERIT_TO_SUBNET6);
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,14 +192,14 @@ size_t SimpleParser6::deriveParameters(isc::data::ElementPtr global) {
|
||||
// if defined there.
|
||||
// Then try to inherit them from global.
|
||||
cnt += SimpleParser::deriveParams(global, net,
|
||||
INHERIT_GLOBAL_TO_SUBNET6);
|
||||
INHERIT_TO_SUBNET6);
|
||||
|
||||
// Now we need to go thrugh all the subnets in this net.
|
||||
subnets = net->get("subnet6");
|
||||
if (subnets) {
|
||||
BOOST_FOREACH(ElementPtr single_subnet, subnets->listValue()) {
|
||||
cnt += SimpleParser::deriveParams(net, single_subnet,
|
||||
INHERIT_GLOBAL_TO_SUBNET6);
|
||||
INHERIT_TO_SUBNET6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,10 @@ public:
|
||||
static const isc::data::SimpleDefaults OPTION6_DEFAULTS;
|
||||
static const isc::data::SimpleDefaults GLOBAL6_DEFAULTS;
|
||||
static const isc::data::SimpleDefaults SUBNET6_DEFAULTS;
|
||||
static const isc::data::SimpleDefaults SHARED_SUBNET6_DEFAULTS;
|
||||
static const isc::data::SimpleDefaults SHARED_NETWORK6_DEFAULTS;
|
||||
static const isc::data::SimpleDefaults IFACE6_DEFAULTS;
|
||||
static const isc::data::ParamsList INHERIT_GLOBAL_TO_SUBNET6;
|
||||
static const isc::data::ParamsList INHERIT_TO_SUBNET6;
|
||||
};
|
||||
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user