Commit 46244482 authored by Marcin Siodelski's avatar Marcin Siodelski

[5305] Migrated server code and tests from Subnet class to Network class.

parent c5e695d3
......@@ -148,7 +148,7 @@ Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine,
}
// Find static reservations if not disabled for our subnet.
if (subnet->getHostReservationMode() != Subnet::HR_DISABLED) {
if (subnet->getHostReservationMode() != Network::HR_DISABLED) {
// Before we can check for static reservations, we need to prepare a set
// of identifiers to be used for this.
setHostIdentifiers();
......
......@@ -4316,22 +4316,22 @@ TEST_F(Dhcp4ParserTest, hostReservationPerSubnet) {
Subnet4Ptr subnet;
subnet = subnets->selectSubnet(IOAddress("192.0.2.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Subnet::HR_ALL, subnet->getHostReservationMode());
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
// Subnet 2
subnet = subnets->selectSubnet(IOAddress("192.0.3.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Subnet::HR_OUT_OF_POOL, subnet->getHostReservationMode());
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
// Subnet 3
subnet = subnets->selectSubnet(IOAddress("192.0.4.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Subnet::HR_DISABLED, subnet->getHostReservationMode());
EXPECT_EQ(Network::HR_DISABLED, subnet->getHostReservationMode());
// Subnet 4
subnet = subnets->selectSubnet(IOAddress("192.0.5.1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Subnet::HR_ALL, subnet->getHostReservationMode());
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
}
/// Check that the decline-probation-period has a default value when not
......
......@@ -270,7 +270,7 @@ HWAddrPtr Dhcpv4SrvTest::generateHWAddr(size_t size /*= 6*/) {
}
void Dhcpv4SrvTest::checkAddressParams(const Pkt4Ptr& rsp,
const SubnetPtr subnet,
const Subnet4Ptr subnet,
bool t1_present,
bool t2_present) {
......
......@@ -326,7 +326,7 @@ public:
/// present (false)
/// @param t2_present check that t2 must be present (true) or must not be
/// present (false)
void checkAddressParams(const Pkt4Ptr& rsp, const SubnetPtr subnet,
void checkAddressParams(const Pkt4Ptr& rsp, const Subnet4Ptr subnet,
bool t1_present = false,
bool t2_present = false);
......
......@@ -309,7 +309,7 @@ Dhcpv6Srv::initContext(const Pkt6Ptr& pkt, AllocEngine::ClientContext6& ctx) {
// are stored in order of preference. The server will use them in that
// order to search for host reservations.
if (ctx.subnet_ &&
(ctx.subnet_->getHostReservationMode() != Subnet::HR_DISABLED)) {
(ctx.subnet_->getHostReservationMode() != Network::HR_DISABLED)) {
const ConstCfgHostOperationsPtr cfg =
CfgMgr::instance().getCurrentCfg()->getCfgHostOperations6();
BOOST_FOREACH(const Host::IdentifierType& id_type,
......
......@@ -4692,22 +4692,22 @@ TEST_F(Dhcp6ParserTest, hostReservationPerSubnet) {
Subnet6Ptr subnet;
subnet = subnets->selectSubnet(IOAddress("2001:db8:1::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Subnet::HR_ALL, subnet->getHostReservationMode());
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
// Subnet 2
subnet = subnets->selectSubnet(IOAddress("2001:db8:2::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Subnet::HR_OUT_OF_POOL, subnet->getHostReservationMode());
EXPECT_EQ(Network::HR_OUT_OF_POOL, subnet->getHostReservationMode());
// Subnet 3
subnet = subnets->selectSubnet(IOAddress("2001:db8:3::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Subnet::HR_DISABLED, subnet->getHostReservationMode());
EXPECT_EQ(Network::HR_DISABLED, subnet->getHostReservationMode());
// Subnet 4
subnet = subnets->selectSubnet(IOAddress("2001:db8:4::1"));
ASSERT_TRUE(subnet);
EXPECT_EQ(Subnet::HR_ALL, subnet->getHostReservationMode());
EXPECT_EQ(Network::HR_ALL, subnet->getHostReservationMode());
}
/// The goal of this test is to verify that configuration can include
......
......@@ -18,6 +18,7 @@
#include <dhcpsrv/host.h>
#include <dhcpsrv/lease_mgr_factory.h>
#include <dhcpsrv/ncr_generator.h>
#include <dhcpsrv/network.h>
#include <hooks/callout_handle.h>
#include <hooks/hooks_manager.h>
#include <dhcpsrv/callout_handle_store.h>
......@@ -570,7 +571,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
}
// Check which host reservation mode is supported in this subnet.
Subnet::HRMode hr_mode = ctx.subnet_->getHostReservationMode();
Network::HRMode hr_mode = ctx.subnet_->getHostReservationMode();
Lease6Collection leases;
......@@ -597,7 +598,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
// it has been reserved for us we would have already allocated a lease.
ConstHostPtr host;
if (hr_mode != Subnet::HR_DISABLED) {
if (hr_mode != Network::HR_DISABLED) {
host = HostMgr::instance().get6(ctx.subnet_->getID(), hint);
}
......@@ -633,7 +634,7 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
if (lease->expired()) {
ConstHostPtr host;
if (hr_mode != Subnet::HR_DISABLED) {
if (hr_mode != Network::HR_DISABLED) {
host = HostMgr::instance().get6(ctx.subnet_->getID(), hint);
}
......@@ -677,7 +678,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 (hr_mode == Subnet::HR_ALL &&
if (hr_mode == Network::HR_ALL &&
HostMgr::instance().get6(ctx.subnet_->getID(), candidate)) {
// Don't allocate.
......@@ -847,7 +848,7 @@ AllocEngine::removeNonmatchingReservedLeases6(ClientContext6& ctx,
// host reservation is disabled (so there are no reserved leases),
// just return.
if (existing_leases.empty() || !ctx.subnet_ ||
(ctx.subnet_->getHostReservationMode() == Subnet::HR_DISABLED) ) {
(ctx.subnet_->getHostReservationMode() == Network::HR_DISABLED) ) {
return;
}
......
......@@ -11,6 +11,10 @@ using namespace isc::data;
namespace isc {
namespace dhcp {
Network::RelayInfo::RelayInfo(const isc::asiolink::IOAddress& addr)
:addr_(addr) {
}
bool
Network::clientSupported(const isc::dhcp::ClientClasses& classes) const {
if (white_list_.empty()) {
......@@ -72,6 +76,25 @@ Network::toElement() const {
Element::create(static_cast<long long>
(getValid().get())));
// Set reservation mode
Network::HRMode hrmode = getHostReservationMode();
std::string mode;
switch (hrmode) {
case HR_DISABLED:
mode = "disabled";
break;
case HR_OUT_OF_POOL:
mode = "out-of-pool";
break;
case HR_ALL:
mode = "all";
break;
default:
isc_throw(ToElementError,
"invalid host reservation mode: " << hrmode);
}
map->set("reservation-mode", Element::create(mode));
// Set options
ConstCfgOptionPtr opts = getCfgOption();
map->set("option-data", opts->toElement());
......
......@@ -317,7 +317,7 @@ RelayInfoParser::RelayInfoParser(const Option::Universe& family)
};
void
RelayInfoParser::parse(const isc::dhcp::Subnet::RelayInfoPtr& cfg,
RelayInfoParser::parse(const isc::dhcp::Network::RelayInfoPtr& cfg,
ConstElementPtr relay_info) {
// There is only one parameter which is mandatory
IOAddress ip = getAddress(relay_info, "ip-address");
......@@ -333,7 +333,7 @@ RelayInfoParser::parse(const isc::dhcp::Subnet::RelayInfoPtr& cfg,
// Ok, we're done with parsing. Let's store the result in the structure
// we were given as configuration storage.
*cfg = isc::dhcp::Subnet::RelayInfo(ip);
*cfg = isc::dhcp::Network::RelayInfo(ip);
}
//****************************** PoolParser ********************************
......@@ -491,7 +491,7 @@ SubnetConfigParser::SubnetConfigParser(uint16_t family)
address_family_(family),
options_(new CfgOption()) {
string addr = family == AF_INET ? "0.0.0.0" : "::";
relay_info_.reset(new isc::dhcp::Subnet::RelayInfo(IOAddress(addr)));
relay_info_.reset(new isc::dhcp::Network::RelayInfo(IOAddress(addr)));
}
SubnetPtr
......@@ -521,15 +521,15 @@ SubnetConfigParser::parse(ConstElementPtr subnet) {
return (subnet_);
}
Subnet::HRMode
Network::HRMode
SubnetConfigParser::hrModeFromText(const std::string& txt) {
if ( (txt.compare("disabled") == 0) ||
(txt.compare("off") == 0) ) {
return (Subnet::HR_DISABLED);
return (Network::HR_DISABLED);
} else if (txt.compare("out-of-pool") == 0) {
return (Subnet::HR_OUT_OF_POOL);
return (Network::HR_OUT_OF_POOL);
} else if (txt.compare("all") == 0) {
return (Subnet::HR_ALL);
return (Network::HR_ALL);
} else {
isc_throw(BadValue, "Can't convert '" << txt
<< "' into any valid reservation-mode values");
......@@ -585,47 +585,6 @@ SubnetConfigParser::createSubnet(ConstElementPtr params) {
ex.what() << " (" << params->getPosition() << ")");
}
}
// Now configure parameters that are common for v4 and v6:
// Get interface name. If it is defined, then the subnet is available
// directly over specified network interface.
std::string iface = getString(params, "interface");
if (!iface.empty()) {
if (!IfaceMgr::instance().getIface(iface)) {
ConstElementPtr error = params->get("interface");
isc_throw(DhcpConfigError, "Specified network interface name " << iface
<< " for subnet " << subnet_->toText()
<< " is not present in the system ("
<< error->getPosition() << ")");
}
subnet_->setIface(iface);
}
// Let's set host reservation mode. If not specified, the default value of
// all will be used.
try {
std::string hr_mode = getString(params, "reservation-mode");
subnet_->setHostReservationMode(hrModeFromText(hr_mode));
} catch (const BadValue& ex) {
isc_throw(DhcpConfigError, "Failed to process specified value "
" of reservation-mode parameter: " << ex.what()
<< "(" << getPosition("reservation-mode", params) << ")");
}
// Try setting up client class.
string client_class = getString(params, "client-class");
if (!client_class.empty()) {
subnet_->allowClientClass(client_class);
}
// Here globally defined options were merged to the subnet specific
// options but this is no longer the case (they have a different
// and not consecutive priority).
// Copy options to the subnet configuration.
options_->copyTo(*subnet_->getCfgOption());
}
//****************************** Subnet4ConfigParser *************************
......@@ -739,6 +698,38 @@ Subnet4ConfigParser::initSubnet(data::ConstElementPtr params,
<< next_server << "(" << pos << ")");
}
// Get interface name. If it is defined, then the subnet is available
// directly over specified network interface.
std::string iface = getString(params, "interface");
if (!iface.empty()) {
if (!IfaceMgr::instance().getIface(iface)) {
ConstElementPtr error = params->get("interface");
isc_throw(DhcpConfigError, "Specified network interface name " << iface
<< " for subnet " << subnet4->toText()
<< " is not present in the system ("
<< error->getPosition() << ")");
}
subnet4->setIface(iface);
}
// Let's set host reservation mode. If not specified, the default value of
// all will be used.
try {
std::string hr_mode = getString(params, "reservation-mode");
subnet4->setHostReservationMode(hrModeFromText(hr_mode));
} catch (const BadValue& ex) {
isc_throw(DhcpConfigError, "Failed to process specified value "
" of reservation-mode parameter: " << ex.what()
<< "(" << getPosition("reservation-mode", params) << ")");
}
// Try setting up client class.
string client_class = getString(params, "client-class");
if (!client_class.empty()) {
subnet4->allowClientClass(client_class);
}
// 4o6 specific parameter: 4o6-interface. If not explicitly specified,
// it will have the default value of "".
string iface4o6 = getString(params, "4o6-interface");
......@@ -781,6 +772,13 @@ Subnet4ConfigParser::initSubnet(data::ConstElementPtr params,
/// client-class processing is now generic and handled in the common
/// code (see isc::data::SubnetConfigParser::createSubnet)
// Here globally defined options were merged to the subnet specific
// options but this is no longer the case (they have a different
// and not consecutive priority).
// Copy options to the subnet configuration.
options_->copyTo(*subnet4->getCfgOption());
}
//**************************** Subnets4ListConfigParser **********************
......@@ -1056,8 +1054,42 @@ Subnet6ConfigParser::initSubnet(data::ConstElementPtr params,
subnet6->setInterfaceId(opt);
}
// Get interface name. If it is defined, then the subnet is available
// directly over specified network interface.
if (!iface.empty()) {
if (!IfaceMgr::instance().getIface(iface)) {
ConstElementPtr error = params->get("interface");
isc_throw(DhcpConfigError, "Specified network interface name " << iface
<< " for subnet " << subnet6->toText()
<< " is not present in the system ("
<< error->getPosition() << ")");
}
subnet6->setIface(iface);
}
// Let's set host reservation mode. If not specified, the default value of
// all will be used.
try {
std::string hr_mode = getString(params, "reservation-mode");
subnet6->setHostReservationMode(hrModeFromText(hr_mode));
} catch (const BadValue& ex) {
isc_throw(DhcpConfigError, "Failed to process specified value "
" of reservation-mode parameter: " << ex.what()
<< "(" << getPosition("reservation-mode", params) << ")");
}
// Try setting up client class.
string client_class = getString(params, "client-class");
if (!client_class.empty()) {
subnet6->allowClientClass(client_class);
}
/// client-class processing is now generic and handled in the common
/// code (see isc::data::SubnetConfigParser::createSubnet)
// Copy options to the subnet configuration.
options_->copyTo(*subnet6->getCfgOption());
}
//**************************** Subnet6ListConfigParser ********************
......
......@@ -14,6 +14,7 @@
#include <dhcpsrv/d2_client_cfg.h>
#include <dhcpsrv/cfg_iface.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/network.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/cfg_option_def.h>
#include <dhcpsrv/cfg_mac_source.h>
......@@ -521,7 +522,7 @@ public:
///
/// @param cfg configuration will be stored here
/// @param relay_info JSON structure holding relay parameters to parse
void parse(const isc::dhcp::Subnet::RelayInfoPtr& cfg,
void parse(const isc::dhcp::Network::RelayInfoPtr& cfg,
isc::data::ConstElementPtr relay_info);
private:
......@@ -593,7 +594,7 @@ protected:
/// @throw BadValue if the text cannot be converted.
///
/// @return one of allowed HRMode values
static Subnet::HRMode hrModeFromText(const std::string& txt);
static Network::HRMode hrModeFromText(const std::string& txt);
private:
......@@ -616,7 +617,7 @@ protected:
uint16_t address_family_;
/// Pointer to relay information
isc::dhcp::Subnet::RelayInfoPtr relay_info_;
isc::dhcp::Network::RelayInfoPtr relay_info_;
/// Pointer to the options configuration.
CfgOptionPtr options_;
......
......@@ -50,23 +50,12 @@ namespace dhcp {
SubnetID Subnet::static_id_ = 1;
Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& valid_lifetime,
const isc::dhcp::Subnet::RelayInfo& relay,
const SubnetID id)
: Network(), id_(id == 0 ? generateNextID() : id), prefix_(prefix),
: id_(id == 0 ? generateNextID() : id), prefix_(prefix),
prefix_len_(len),
last_allocated_ia_(lastAddrInPrefix(prefix, len)),
last_allocated_ta_(lastAddrInPrefix(prefix, len)),
last_allocated_pd_(lastAddrInPrefix(prefix, len)) {
// Relay info.
setRelayInfo(relay);
// Timers.
setT1(t1);
setT2(t2);
setValid(valid_lifetime);
if ((prefix.isV6() && len > 128) ||
(prefix.isV4() && len > 32)) {
isc_throw(BadValue,
......@@ -74,10 +63,6 @@ Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
}
}
Subnet::RelayInfo::RelayInfo(const isc::asiolink::IOAddress& addr)
:addr_(addr) {
}
bool
Subnet::inRange(const isc::asiolink::IOAddress& addr) const {
IOAddress first = firstAddrInPrefix(prefix_, prefix_len_);
......@@ -177,12 +162,18 @@ Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& valid_lifetime,
const SubnetID id)
: Subnet(prefix, length, t1, t2, valid_lifetime, RelayInfo(IOAddress("0.0.0.0")), id),
: Subnet(prefix, length, id), Network(),
siaddr_(IOAddress("0.0.0.0")), match_client_id_(true) {
if (!prefix.isV4()) {
isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText()
<< " specified in subnet4");
}
// Relay info.
setRelayInfo(IOAddress::IPV4_ZERO_ADDRESS());
// Timers.
setT1(t1);
setT2(t2);
setValid(valid_lifetime);
}
void Subnet4::setSiaddr(const isc::asiolink::IOAddress& siaddr) {
......@@ -424,12 +415,19 @@ Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length,
const Triplet<uint32_t>& preferred_lifetime,
const Triplet<uint32_t>& valid_lifetime,
const SubnetID id)
:Subnet(prefix, length, t1, t2, valid_lifetime, RelayInfo(IOAddress("::")), id),
:Subnet(prefix, length, id), Network(),
preferred_(preferred_lifetime), rapid_commit_(false) {
if (!prefix.isV6()) {
isc_throw(BadValue, "Non IPv6 prefix " << prefix
<< " specified in subnet6");
}
// Relay info.
setRelayInfo(RelayInfo(IOAddress::IPV6_ZERO_ADDRESS()));
// Timers.
setT1(t1);
setT2(t2);
setValid(valid_lifetime);
}
void Subnet6::checkType(Lease::Type type) const {
......@@ -443,7 +441,7 @@ void Subnet6::checkType(Lease::Type type) const {
data::ElementPtr
Subnet::toElement() const {
ElementPtr map = Network::toElement();
ElementPtr map = Element::createMap();
// Set subnet id
SubnetID id = getID();
......@@ -452,25 +450,6 @@ Subnet::toElement() const {
// Set subnet
map->set("subnet", Element::create(toText()));
// Set reservation mode
Subnet::HRMode hrmode = getHostReservationMode();
std::string mode;
switch (hrmode) {
case Subnet::HR_DISABLED:
mode = "disabled";
break;
case Subnet::HR_OUT_OF_POOL:
mode = "out-of-pool";
break;
case Subnet::HR_ALL:
mode = "all";
break;
default:
isc_throw(ToElementError,
"invalid host reservation mode: " << hrmode);
}
map->set("reservation-mode", Element::create(mode));
return (map);
}
......@@ -478,6 +457,9 @@ data::ElementPtr
Subnet4::toElement() const {
// Prepare the map
ElementPtr map = Subnet::toElement();
ElementPtr network_map = Network::toElement();
merge(map, network_map);
// Set match-client-id
map->set("match-client-id", Element::create(getMatchClientId()));
......@@ -506,6 +488,9 @@ data::ElementPtr
Subnet6::toElement() const {
// Prepare the map
ElementPtr map = Subnet::toElement();
ElementPtr network_map = Network::toElement();
merge(map, network_map);
// Set interface-id
const OptionPtr& ifaceid = getInterfaceId();
......
......@@ -28,7 +28,7 @@
namespace isc {
namespace dhcp {
class Subnet : public Network {
class Subnet : public data::CfgToElement {
// Assignable network is our friend to allow it to call
// @ref Subnet::setSharedNetwork private function.
......@@ -241,17 +241,9 @@ protected:
///
/// @param prefix subnet prefix
/// @param len prefix length for the subnet
/// @param t1 T1 (renewal-time) timer, expressed in seconds
/// @param t2 T2 (rebind-time) timer, expressed in seconds
/// @param valid_lifetime valid lifetime of leases in this subnet (in seconds)
/// @param relay optional relay information (currently with address only)
/// @param id arbitrary subnet id, value of 0 triggers autogeneration
/// of subnet id
Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& valid_lifetime,
const isc::dhcp::Subnet::RelayInfo& relay,
const SubnetID id);
/// @brief virtual destructor
......@@ -367,7 +359,7 @@ typedef boost::shared_ptr<Subnet> SubnetPtr;
/// @brief A configuration holder for IPv4 subnet.
///
/// This class represents an IPv4 subnet.
class Subnet4 : public Subnet {
class Subnet4 : public Subnet, public Network {
public:
/// @brief Constructor with all parameters
......@@ -474,7 +466,7 @@ typedef boost::shared_ptr<Subnet4> Subnet4Ptr;
/// @brief A configuration holder for IPv6 subnet.
///
/// This class represents an IPv6 subnet.
class Subnet6 : public Subnet {
class Subnet6 : public Subnet, public Network {
public:
/// @brief Constructor with all parameters
......
......@@ -1709,13 +1709,13 @@ TEST_F(AllocEngine4Test, findReservation) {
// Regardless of the host reservation mode, the host should be
// always returned when findReservation() is called.
subnet_->setHostReservationMode(Subnet::HR_DISABLED);
subnet_->setHostReservationMode(Network::HR_DISABLED);
ASSERT_NO_THROW(engine.findReservation(ctx));
EXPECT_TRUE(ctx.host_);
EXPECT_EQ(ctx.host_->getIPv4Reservation(), host->getIPv4Reservation());
// Check the third possible reservation mode.
subnet_->setHostReservationMode(Subnet::HR_OUT_OF_POOL);
subnet_->setHostReservationMode(Network::HR_OUT_OF_POOL);
ASSERT_NO_THROW(engine.findReservation(ctx));
EXPECT_TRUE(ctx.host_);
EXPECT_EQ(ctx.host_->getIPv4Reservation(), host->getIPv4Reservation());
......
......@@ -2272,7 +2272,7 @@ TEST_F(ParseConfigTest, validRelayInfo4) {
ElementPtr json = Element::fromJSON(config_str);
// We need to set the default ip-address to something.
Subnet::RelayInfoPtr result(new Subnet::RelayInfo(asiolink::IOAddress("0.0.0.0")));
Network::RelayInfoPtr result(new Network::RelayInfo(asiolink::IOAddress("0.0.0.0")));
RelayInfoParser parser(Option::V4);
......@@ -2305,7 +2305,7 @@ TEST_F(ParseConfigTest, bogusRelayInfo4) {
ElementPtr json_bogus3 = Element::fromJSON(config_str_bogus3);
// We need to set the default ip-address to something.