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