Commit d996bf25 authored by Francis Dupont's avatar Francis Dupont

[3389a] Commit before regen

parent 4fa4c9a0
......@@ -719,6 +719,23 @@ temporarily override a list of interface names and listen on all interfaces.
supported on the particular OS, the server will issue a warning and
fall back to use IP/UDP sockets.</para>
</note>
<para>Interfaces are re-detected at each reconfiguration. This behavior
can be disabled by setting <command>re-detect</command> value to
<userinput>false</userinput>, for instance:
<screen>
"Dhcp4": {
"interfaces-config": {
"interfaces": [ <userinput>"eth1", "eth3"</userinput> ],
"re-detect": <userinput>false</userinput>
},
...
}
</screen>
Note interfaces are not re-detected during <command>config-test</command>.
</para>
</section>
<section id="dhcpinform-unicast-issues">
......
......@@ -625,6 +625,13 @@ for MySQL and PostgreSQL databases.</para></note>
It is anticipated that this will form of usage only be used where it is desired to
temporarily override a list of interface names and listen on all interfaces.
</para>
<para>As for the DHCPv4 server binding to specific addresses and
disabling re-detection of interfaces are supported. But
<command>dhcp-socket-type</command> is not because DHCPv6 uses
UDP/IPv6 sockets only.
</para>
</section>
<section id="ipv6-subnet-id">
......
......@@ -483,9 +483,18 @@ configureDhcp4Server(Dhcpv4Srv&, isc::data::ConstElementPtr config_set,
}
if (config_pair.first == "interfaces-config") {
ElementPtr ifaces_cfg =
boost::const_pointer_cast<Element>(config_pair.second);
if (check_only) {
// No re-detection in check only mode
ifaces_cfg->set("re-detect", Element::create(false));
} else if (!ifaces_cfg->contains("re-detect")) {
// Else the default is to re-detect
ifaces_cfg->set("re-detect", Element::create(true));
}
IfacesConfigParser parser(AF_INET);
CfgIfacePtr cfg_iface = srv_cfg->getCfgIface();
parser.parse(cfg_iface, config_pair.second);
parser.parse(cfg_iface, ifaces_cfg);
continue;
}
......
......@@ -49,7 +49,9 @@ namespace {
class NakedControlledDhcpv4Srv: public ControlledDhcpv4Srv {
// "Naked" DHCPv4 server, exposes internal fields
public:
NakedControlledDhcpv4Srv():ControlledDhcpv4Srv(0) { }
NakedControlledDhcpv4Srv():ControlledDhcpv4Srv(0) {
CfgMgr::instance().setFamily(AF_INET);
}
/// Expose internal methods for the sake of testing
using Dhcpv4Srv::receivePacket;
......
......@@ -608,6 +608,9 @@ Dhcpv4SrvTest::configure(const std::string& config, NakedDhcpv4Srv& srv,
ASSERT_NO_THROW(json = parseJSON(config));
ConstElementPtr status;
// Patch the re-detect flag
patchIfacesReDetect(json);
// Configure the server and make sure the config is accepted
EXPECT_NO_THROW(status = configureDhcp4Server(srv, json));
ASSERT_TRUE(status);
......
......@@ -479,6 +479,18 @@ public:
NakedDhcpv4Srv srv_;
};
/// @brief Patch the server config to add interface-config/re-detect=false
/// @param json the server config
inline void
patchIfacesReDetect(isc::data::ConstElementPtr json) {
isc::data::ConstElementPtr ifaces_cfg = json->get("interfaces-config");
if (ifaces_cfg) {
isc::data::ElementPtr mutable_cfg =
boost::const_pointer_cast<isc::data::Element>(ifaces_cfg);
mutable_cfg->set("re-detect", isc::data::Element::create(false));
}
}
/// @brief Runs parser in JSON mode, useful for parser testing
///
/// @param in string to be parsed
......@@ -503,7 +515,10 @@ parseDHCP4(const std::string& in, bool verbose = false)
{
try {
isc::dhcp::Parser4Context ctx;
return (ctx.parseString(in, isc::dhcp::Parser4Context::SUBPARSER_DHCP4));
isc::data::ElementPtr json;
json = ctx.parseString(in, isc::dhcp::Parser4Context::SUBPARSER_DHCP4);
patchIfacesReDetect(json);
return (json);
}
catch (const std::exception& ex) {
if (verbose) {
......
This diff is collapsed.
......@@ -694,9 +694,18 @@ configureDhcp6Server(Dhcpv6Srv&, isc::data::ConstElementPtr config_set,
}
if (config_pair.first == "interfaces-config") {
ElementPtr ifaces_cfg =
boost::const_pointer_cast<Element>(config_pair.second);
if (check_only) {
// No re-detection in check only mode
ifaces_cfg->set("re-detect", Element::create(false));
} else if (!ifaces_cfg->contains("re-detect")) {
// Else the default is to re-detect
ifaces_cfg->set("re-detect", Element::create(true));
}
IfacesConfigParser parser(AF_INET6);
CfgIfacePtr cfg_iface = srv_config->getCfgIface();
parser.parse(cfg_iface, config_pair.second);
parser.parse(cfg_iface, ifaces_cfg);
continue;
}
......
......@@ -49,6 +49,7 @@ class NakedControlledDhcpv6Srv: public ControlledDhcpv6Srv {
// "Naked" DHCPv6 server, exposes internal fields
public:
NakedControlledDhcpv6Srv():ControlledDhcpv6Srv(DHCP6_SERVER_PORT + 10000) {
CfgMgr::instance().setFamily(AF_INET6);
}
/// Expose internal methods for the sake of testing
......@@ -576,7 +577,7 @@ TEST_F(CtrlChannelDhcpv6SrvTest, set_config) {
typedef std::map<std::string, isc::data::ConstElementPtr> ElementMap;
// This test checks which commands are registered by the DHCPv4 server.
// This test checks which commands are registered by the DHCPv6 server.
TEST_F(CtrlDhcpv6SrvTest, commandsRegistration) {
ConstElementPtr list_cmds = createCommand("list-commands");
......
......@@ -702,6 +702,9 @@ Dhcpv6SrvTest::configure(const std::string& config, NakedDhcpv6Srv& srv) {
ASSERT_NO_THROW(json = parseJSON(config));
ConstElementPtr status;
// Patch the re-detect flag
patchIfacesReDetect(json);
// Configure the server and make sure the config is accepted
EXPECT_NO_THROW(status = configureDhcp6Server(srv, json));
ASSERT_TRUE(status);
......
......@@ -639,6 +639,18 @@ public:
NakedDhcpv6Srv srv_;
};
/// @brief Patch the server config to add interface-config/re-detect=false
/// @param json the server config
inline void
patchIfacesReDetect(isc::data::ConstElementPtr json) {
isc::data::ConstElementPtr ifaces_cfg = json->get("interfaces-config");
if (ifaces_cfg) {
isc::data::ElementPtr mutable_cfg =
boost::const_pointer_cast<isc::data::Element>(ifaces_cfg);
mutable_cfg->set("re-detect", isc::data::Element::create(false));
}
}
/// @brief Runs parser in JSON mode, useful for parser testing
///
/// @param in string to be parsed
......@@ -663,7 +675,10 @@ parseDHCP6(const std::string& in, bool verbose = false)
{
try {
isc::dhcp::Parser6Context ctx;
return (ctx.parseString(in, isc::dhcp::Parser6Context::SUBPARSER_DHCP6));
isc::data::ElementPtr json;
json = ctx.parseString(in, isc::dhcp::Parser6Context::SUBPARSER_DHCP6);
patchIfacesReDetect(json);
return (json);
}
catch (const std::exception& ex) {
if (verbose) {
......
This diff is collapsed.
......@@ -22,7 +22,7 @@ namespace dhcp {
const char* CfgIface::ALL_IFACES_KEYWORD = "*";
CfgIface::CfgIface()
: wildcard_used_(false), socket_type_(SOCKET_RAW) {
: wildcard_used_(false), socket_type_(SOCKET_RAW), re_detect_(false) {
}
void
......@@ -425,6 +425,9 @@ CfgIface::toElement() const {
result->set("dhcp-socket-type", Element::create(std::string("udp")));
}
// Set re-detect
result->set("re-detect", Element::create(re_detect_));
return (result);
}
......
......@@ -257,6 +257,13 @@ public:
/// @return a pointer to unparsed configuration
virtual isc::data::ElementPtr toElement() const;
/// @brief Set the re-detect flag
///
/// @param re_detect the new value of the flag
void setReDetect(bool re_detect) {
re_detect_ = re_detect;
}
private:
/// @brief Checks if multiple IPv4 addresses has been activated on any
......@@ -330,6 +337,9 @@ private:
/// @brief A type of the sockets used by the DHCP server.
SocketType socket_type_;
/// @brief A boolean value which reflects current re-detect setting
bool re_detect_;
};
/// @brief A pointer to the @c CfgIface .
......
......@@ -41,16 +41,18 @@ void
IfacesConfigParser::parse(const CfgIfacePtr& cfg,
const isc::data::ConstElementPtr& ifaces_config) {
// Get the pointer to the interface configuration.
// Check for re-detect before calling parseInterfacesList()
bool re_detect = getBoolean(ifaces_config, "re-detect");
cfg->setReDetect(re_detect);
if (re_detect) {
IfaceMgr::instance().clearIfaces();
IfaceMgr::instance().detectIfaces();
}
bool socket_type_specified = false;
BOOST_FOREACH(ConfigPair element, ifaces_config->mapValue()) {
try {
// Check for re-detect before calling parseInterfacesList()
if (element.first == "re-detect") {
if (element.second->boolValue()) {
IfaceMgr::instance().clearIfaces();
IfaceMgr::instance().detectIfaces();
}
continue;
}
......
......@@ -371,7 +371,8 @@ TEST_F(CfgIfaceTest, unparse) {
// Check unparse
std::string expected =
"{ \"interfaces\": [ \"*\", \"eth0\", \"eth1/192.0.2.3\" ] }";
"{ \"interfaces\": [ \"*\", \"eth0\", \"eth1/192.0.2.3\" ], "
"\"re-detect\": false }";
runToElementTest<CfgIface>(expected, cfg4);
// Now check IPv6
......@@ -381,7 +382,8 @@ TEST_F(CfgIfaceTest, unparse) {
EXPECT_NO_THROW(cfg6.use(AF_INET6, "eth0/2001:db8:1::1"));
expected =
"{ \"interfaces\": [ \"*\", \"eth1\", \"eth0/2001:db8:1::1\" ] }";
"{ \"interfaces\": [ \"*\", \"eth1\", \"eth0/2001:db8:1::1\" ], "
"\"re-detect\": false }";
runToElementTest<CfgIface>(expected, cfg6);
}
......@@ -402,7 +404,8 @@ TEST(CfgIfaceNoStubTest, useSocketType) {
// Check unparse
std::string expected = "{\n"
" \"interfaces\": [ ],\n"
" \"dhcp-socket-type\": \"udp\" }";
" \"dhcp-socket-type\": \"udp\",\n"
" \"re-detect\": false }";
runToElementTest<CfgIface>(expected, cfg);
// Select raw sockets.
......
......@@ -53,7 +53,8 @@ TEST_F(IfacesConfigParserTest, interfaces) {
IfaceMgrTestConfig test_config(true);
// Configuration with one interface.
std::string config = "{ ""\"interfaces\": [ \"eth0\" ] }";
std::string config =
"{ \"interfaces\": [ \"eth0\" ], \"re-detect\": false }";
ElementPtr config_element = Element::fromJSON(config);
......@@ -81,7 +82,7 @@ TEST_F(IfacesConfigParserTest, interfaces) {
// Try similar configuration but this time add a wildcard interface
// to see if sockets will open on all interfaces.
config = "{ \"interfaces\": [ \"eth0\", \"*\" ] }";
config = "{ \"interfaces\": [ \"eth0\", \"*\" ], \"re-detect\": false }";
config_element = Element::fromJSON(config);
cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
......@@ -106,7 +107,8 @@ TEST_F(IfacesConfigParserTest, socketTypeRaw) {
// Configuration with a raw socket selected.
std::string config = "{ ""\"interfaces\": [ ],"
" \"dhcp-socket-type\": \"raw\" }";
" \"dhcp-socket-type\": \"raw\","
" \"re-detect\": false }";
ElementPtr config_element = Element::fromJSON(config);
......@@ -132,7 +134,8 @@ TEST_F(IfacesConfigParserTest, socketTypeDatagram) {
// Configuration with a datagram socket selected.
std::string config = "{ \"interfaces\": [ ],"
" \"dhcp-socket-type\": \"udp\" }";
" \"dhcp-socket-type\": \"udp\","
" \"re-detect\": false }";
ElementPtr config_element = Element::fromJSON(config);
......@@ -160,14 +163,16 @@ TEST_F(IfacesConfigParserTest, socketTypeInvalid) {
IfacesConfigParser parser4(AF_INET);
CfgIfacePtr cfg_iface = CfgMgr::instance().getStagingCfg()->getCfgIface();
std::string config = "{ \"interfaces\": [ ],"
"\"dhcp-socket-type\": \"default\" }";
"\"dhcp-socket-type\": \"default\","
" \"re-detect\": false }";
ElementPtr config_element = Element::fromJSON(config);
ASSERT_THROW(parser4.parse(cfg_iface, config_element), DhcpConfigError);
// For DHCPv6 we don't accept any socket type.
IfacesConfigParser parser6(AF_INET6);
config = "{ \"interfaces\": [ ],"
" \"dhcp-socket-type\": \"udp\" }";
" \"dhcp-socket-type\": \"udp\","
" \"re-detect\": false }";
config_element = Element::fromJSON(config);
ASSERT_THROW(parser6.parse(cfg_iface, config_element), DhcpConfigError);
}
......
......@@ -437,7 +437,8 @@ TEST_F(SrvConfigTest, unparse) {
std::string defaults = "\"decline-probation-period\": 0,\n";
defaults += "\"dhcp4o6-port\": 0,\n";
defaults += "\"interfaces-config\": { \"interfaces\": [ ] },\n";
defaults += "\"interfaces-config\": { \"interfaces\": [ ],\n";
defaults += " \"re-detect\": false },\n";
defaults += "\"option-def\": [ ],\n";
defaults += "\"option-data\": [ ],\n";
defaults += "\"expired-leases-processing\": ";
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment