mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-10-17 14:26:31 +00:00
[5305] Introduced shared networks holding subnets.
This commit is contained in:
@@ -88,6 +88,7 @@ libkea_dhcpsrv_la_SOURCES =
|
||||
libkea_dhcpsrv_la_SOURCES += addr_utilities.cc addr_utilities.h
|
||||
libkea_dhcpsrv_la_SOURCES += alloc_engine.cc alloc_engine.h
|
||||
libkea_dhcpsrv_la_SOURCES += alloc_engine_log.cc alloc_engine_log.h
|
||||
libkea_dhcpsrv_la_SOURCES += assignable_network.h
|
||||
libkea_dhcpsrv_la_SOURCES += base_host_data_source.h
|
||||
libkea_dhcpsrv_la_SOURCES += callout_handle_store.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_4o6.cc cfg_4o6.h
|
||||
@@ -101,6 +102,8 @@ libkea_dhcpsrv_la_SOURCES += cfg_host_operations.cc cfg_host_operations.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_option.cc cfg_option.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_option_def.cc cfg_option_def.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_rsoo.cc cfg_rsoo.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_shared_networks4.cc cfg_shared_networks4.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_shared_networks6.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_subnets4.cc cfg_subnets4.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_subnets6.cc cfg_subnets6.h
|
||||
libkea_dhcpsrv_la_SOURCES += cfg_mac_source.cc cfg_mac_source.h
|
||||
@@ -138,6 +141,7 @@ libkea_dhcpsrv_la_SOURCES += mysql_host_data_source.cc mysql_host_data_source.h
|
||||
endif
|
||||
|
||||
libkea_dhcpsrv_la_SOURCES += ncr_generator.cc ncr_generator.h
|
||||
libkea_dhcpsrv_la_SOURCES += network.h
|
||||
|
||||
if HAVE_PGSQL
|
||||
libkea_dhcpsrv_la_SOURCES += pgsql_connection.cc pgsql_connection.h
|
||||
@@ -150,6 +154,7 @@ libkea_dhcpsrv_la_SOURCES += cql_lease_mgr.cc cql_lease_mgr.h
|
||||
libkea_dhcpsrv_la_SOURCES += cql_connection.cc cql_connection.h
|
||||
endif
|
||||
libkea_dhcpsrv_la_SOURCES += pool.cc pool.h
|
||||
libkea_dhcpsrv_la_SOURCES += shared_network.cc shared_network.h
|
||||
libkea_dhcpsrv_la_SOURCES += srv_config.cc srv_config.h
|
||||
libkea_dhcpsrv_la_SOURCES += subnet.cc subnet.h
|
||||
libkea_dhcpsrv_la_SOURCES += subnet_id.h
|
||||
@@ -178,6 +183,9 @@ libkea_dhcpsrv_la_SOURCES += parsers/ifaces_config_parser.cc
|
||||
libkea_dhcpsrv_la_SOURCES += parsers/ifaces_config_parser.h
|
||||
libkea_dhcpsrv_la_SOURCES += parsers/option_data_parser.cc
|
||||
libkea_dhcpsrv_la_SOURCES += parsers/option_data_parser.h
|
||||
libkea_dhcpsrv_la_SOURCES += parsers/shared_network_parser.cc
|
||||
libkea_dhcpsrv_la_SOURCES += parsers/shared_network_parser.h
|
||||
libkea_dhcpsrv_la_SOURCES += parsers/shared_networks_list_parser.h
|
||||
libkea_dhcpsrv_la_SOURCES += parsers/simple_parser4.cc
|
||||
libkea_dhcpsrv_la_SOURCES += parsers/simple_parser4.h
|
||||
libkea_dhcpsrv_la_SOURCES += parsers/simple_parser6.cc
|
||||
|
59
src/lib/dhcpsrv/assignable_network.h
Normal file
59
src/lib/dhcpsrv/assignable_network.h
Normal file
@@ -0,0 +1,59 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef ASSIGNABLE_NETWORK_H
|
||||
#define ASSIGNABLE_NETWORK_H
|
||||
|
||||
#include <dhcpsrv/network.h>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
/// @brief Represents a network that can be associated with a subnet.
|
||||
///
|
||||
/// This class represents a network that can be associated with a subnet
|
||||
/// using @c Subnet::setSharedNetwork method. This class is a friend
|
||||
/// of a @ref Subnet class, so it can call its @c Subnet::setSharedNetwork
|
||||
/// private method. Association of a network with a subnet must be always
|
||||
/// conducted using this class. This prevents unwanted replacements of
|
||||
/// shared networks within subnets.
|
||||
class AssignableNetwork : public Network {
|
||||
protected:
|
||||
|
||||
/// @brief Returns shared pointer to this object.
|
||||
///
|
||||
/// This abstract method must be implemented by derived classes to
|
||||
/// return shared pointers the derivation.
|
||||
///
|
||||
/// @return Pointer to this network.
|
||||
virtual NetworkPtr sharedFromThis() = 0;
|
||||
|
||||
/// @brief Associates a subnet with this network.
|
||||
///
|
||||
/// @param subnet Pointer to a subnet to be associated with the network.
|
||||
///
|
||||
/// @tparam SubnetPtr Type of the subnet pointer.
|
||||
template<typename SubnetPtr>
|
||||
void setSharedNetwork(const SubnetPtr& subnet) {
|
||||
subnet->setSharedNetwork(sharedFromThis());
|
||||
}
|
||||
|
||||
/// @brief Removes association of a subnet with a network.
|
||||
///
|
||||
/// @param subnet Pointer to a subnet for which association should be
|
||||
/// removed.
|
||||
///
|
||||
/// @tparam SubnetPtr Type of the subnet pointer.
|
||||
template<typename SubnetPtr>
|
||||
void clearSharedNetwork(const SubnetPtr& subnet) {
|
||||
subnet->setSharedNetwork(NetworkPtr());
|
||||
}
|
||||
};
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
} // end of namespace isc
|
||||
|
||||
#endif // ASSIGNABLE_NETWORK_H
|
17
src/lib/dhcpsrv/cfg_shared_networks4.cc
Normal file
17
src/lib/dhcpsrv/cfg_shared_networks4.cc
Normal file
@@ -0,0 +1,17 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <dhcpsrv/cfg_shared_networks4.h>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
void
|
||||
CfgSharedNetworks4::add(const SharedNetwork4Ptr& network) {
|
||||
}
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
} // end of namespace isc
|
29
src/lib/dhcpsrv/cfg_shared_networks4.h
Normal file
29
src/lib/dhcpsrv/cfg_shared_networks4.h
Normal file
@@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef CFG_SHARED_NETWORKS4_H
|
||||
#define CFG_SHARED_NETWORKS4_H
|
||||
|
||||
#include <cc/cfg_to_element.h>
|
||||
#include <dhcpsrv/shared_network.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
class CfgSharedNetworks4 : public data::CfgToElement {
|
||||
public:
|
||||
|
||||
void add(const SharedNetwork4Ptr& shared_network);
|
||||
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<CfgSharedNetworks4> CfgSharedNetworks4Ptr;
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
} // end of namespace isc
|
||||
|
||||
#endif // CFG_SHARED_NETWORKS4_H
|
26
src/lib/dhcpsrv/cfg_shared_networks6.h
Normal file
26
src/lib/dhcpsrv/cfg_shared_networks6.h
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef CFG_SHARED_NETWORKS6_H
|
||||
#define CFG_SHARED_NETWORKS6_H
|
||||
|
||||
#include <cc/cfg_to_element.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
class CfgSharedNetworks6 : public data::CfgToElement {
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<CfgSharedNetworks6> CfgSharedNetworks6Ptr;
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
} // end of namespace isc
|
||||
|
||||
#endif // CFG_SHARED_NETWORKS6_H
|
74
src/lib/dhcpsrv/network.h
Normal file
74
src/lib/dhcpsrv/network.h
Normal file
@@ -0,0 +1,74 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef NETWORK_H
|
||||
#define NETWORK_H
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
/// @brief Common interface representing a network to which the DHCP clients
|
||||
/// are connected.
|
||||
///
|
||||
/// The most common type of network, in Kea's terminology, is a subnet. The
|
||||
/// @ref Subnet implements this interface. Another types of objects implementing
|
||||
/// this interface are @ref SharedNetwork objects. They group multiple subnets
|
||||
/// together to provide means for extending available address pools (a single
|
||||
/// client may obtain IP address from any of the pools belonging to subnets in
|
||||
/// the shared network), or for selecting a subnet on a given link, depending
|
||||
/// on the class of the client (e.g. cable network case: different subnet is
|
||||
/// selected for cable modems, different one for routers).
|
||||
///
|
||||
/// The subnets and shared networks share many data structures, e.g. DHCP
|
||||
/// options, local interface name, address manipulation methods, thus this
|
||||
/// class provides an abstract interface that must be implemented by derived
|
||||
/// classes and, where appropriate, implements common methods used by the
|
||||
/// derived classes.
|
||||
class Network {
|
||||
public:
|
||||
|
||||
/// @brief Virtual destructor.
|
||||
///
|
||||
/// Does nothing at the moment.
|
||||
virtual ~Network() { };
|
||||
|
||||
/// @brief Sets local name of the interface for which this network is
|
||||
/// selected.
|
||||
///
|
||||
/// If the interface is specified, the server will use the network
|
||||
/// associated with this local interface to allocate IP addresses and
|
||||
/// other resources to a client.
|
||||
///
|
||||
/// @param iface_name Interface name.
|
||||
void setIface(const std::string& iface_name) {
|
||||
iface_name_ = iface_name;
|
||||
}
|
||||
|
||||
/// @brief Returns name of the local interface for which this network is
|
||||
/// selected.
|
||||
///
|
||||
/// @return Interface name as text.
|
||||
std::string getIface() const {
|
||||
return (iface_name_);
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief Holds interface name for which this network is selected.
|
||||
std::string iface_name_;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Pointer to the @ref Network object.
|
||||
typedef boost::shared_ptr<Network> NetworkPtr;
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
} // end of namespace isc
|
||||
|
||||
#endif // NETWORK_H
|
30
src/lib/dhcpsrv/parsers/shared_network_parser.cc
Normal file
30
src/lib/dhcpsrv/parsers/shared_network_parser.cc
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef SHARED_NETWORK_PARSER_H
|
||||
#define SHARED_NETWORK_PARSER_H
|
||||
|
||||
#include <cc/data.h>
|
||||
#include <dhcpsrv/parsers/shared_network_parser.h>
|
||||
#include <dhcpsrv/shared_network.h>
|
||||
|
||||
using namespace isc::data;
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
SharedNetworkParser::~SharedNetworkParser() {
|
||||
}
|
||||
|
||||
SharedNetworkPtr
|
||||
SharedNetworkParser::parse(const ConstElementPtr& shared_network_data) {
|
||||
return (SharedNetworkPtr());
|
||||
}
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
} // end of namespace isc
|
||||
|
||||
#endif // SHARED_NETWORK_PARSER_H
|
30
src/lib/dhcpsrv/parsers/shared_network_parser.h
Normal file
30
src/lib/dhcpsrv/parsers/shared_network_parser.h
Normal file
@@ -0,0 +1,30 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef SHARED_SUBNET_PARSER_H
|
||||
#define SHARED_SUBNET_PARSER_H
|
||||
|
||||
#include <cc/data.h>
|
||||
#include <cc/simple_parser.h>
|
||||
#include <dhcpsrv/shared_network.h>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
class SharedNetworkParser : public isc::data::SimpleParser {
|
||||
public:
|
||||
|
||||
virtual ~SharedNetworkParser();
|
||||
|
||||
virtual SharedNetworkPtr
|
||||
parse(const data::ConstElementPtr& shared_network_data);
|
||||
|
||||
};
|
||||
|
||||
} // enf of namespace isc::dhcp
|
||||
} // end of namespace isc
|
||||
|
||||
#endif // SHARED_SUBNET_PARSER_H
|
37
src/lib/dhcpsrv/parsers/shared_networks_list_parser.h
Normal file
37
src/lib/dhcpsrv/parsers/shared_networks_list_parser.h
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef SHARED_NETWORKS_LIST_PARSER_H
|
||||
#define SHARED_NETWORKS_LIST_PARSER_H
|
||||
|
||||
#include <cc/data.h>
|
||||
#include <cc/dhcp_config_error.h>
|
||||
#include <cc/simple_parser.h>
|
||||
#include <exceptions/exceptions.h>
|
||||
#include <dhcpsrv/subnet.h>
|
||||
#include <dhcpsrv/parsers/shared_network_parser.h>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
template<typename SharedNetworkParserType>
|
||||
class SharedNetworksListParser : public data::SimpleParser {
|
||||
protected:
|
||||
|
||||
template<typename CfgSharedNetworksTypePtr>
|
||||
void parse(const data::ConstElementPtr& shared_networks_list_data,
|
||||
CfgSharedNetworksTypePtr& cfg) {
|
||||
if (shared_networks_list_data->getType() != Element::list) {
|
||||
isc_throw(data::DhcpConfigError, "shared-networks value must be a list");
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
} // end of namespace isc
|
||||
|
||||
#endif // SHARED_NETWORKS_LIST_PARSER_H
|
69
src/lib/dhcpsrv/shared_network.cc
Normal file
69
src/lib/dhcpsrv/shared_network.cc
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <dhcpsrv/shared_network.h>
|
||||
|
||||
using namespace isc::dhcp;
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
NetworkPtr
|
||||
SharedNetwork4::sharedFromThis() {
|
||||
return (shared_from_this());
|
||||
}
|
||||
|
||||
void
|
||||
SharedNetwork4::add(const Subnet4Ptr& subnet) {
|
||||
SharedNetwork::add(subnets_, subnet);
|
||||
}
|
||||
|
||||
void
|
||||
SharedNetwork4::del(const SubnetID& subnet_id) {
|
||||
SharedNetwork::del(subnets_, subnet_id);
|
||||
}
|
||||
|
||||
Subnet4Ptr
|
||||
SharedNetwork4::getSubnet(const SubnetID& subnet_id) const {
|
||||
return (SharedNetwork::getSubnet<Subnet4Ptr>(subnets_, subnet_id));
|
||||
}
|
||||
|
||||
Subnet4Ptr
|
||||
SharedNetwork4::getNextSubnet(const Subnet4Ptr& first_subnet,
|
||||
const Subnet4Ptr& current_subnet) const {
|
||||
return (SharedNetwork::getNextSubnet(subnets_, first_subnet,
|
||||
current_subnet));
|
||||
}
|
||||
|
||||
NetworkPtr
|
||||
SharedNetwork6::sharedFromThis() {
|
||||
return (shared_from_this());
|
||||
}
|
||||
|
||||
void
|
||||
SharedNetwork6::add(const Subnet6Ptr& subnet) {
|
||||
SharedNetwork::add(subnets_, subnet);
|
||||
}
|
||||
|
||||
void
|
||||
SharedNetwork6::del(const SubnetID& subnet_id) {
|
||||
SharedNetwork::del(subnets_, subnet_id);
|
||||
}
|
||||
|
||||
Subnet6Ptr
|
||||
SharedNetwork6::getSubnet(const SubnetID& subnet_id) const {
|
||||
return (SharedNetwork::getSubnet<Subnet6Ptr>(subnets_, subnet_id));
|
||||
}
|
||||
|
||||
Subnet6Ptr
|
||||
SharedNetwork6::getNextSubnet(const Subnet6Ptr& first_subnet,
|
||||
const Subnet6Ptr& current_subnet) const {
|
||||
return (SharedNetwork::getNextSubnet(subnets_, first_subnet,
|
||||
current_subnet));
|
||||
}
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
} // end of namespace isc
|
374
src/lib/dhcpsrv/shared_network.h
Normal file
374
src/lib/dhcpsrv/shared_network.h
Normal file
@@ -0,0 +1,374 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#ifndef SHARED_NETWORK_H
|
||||
#define SHARED_NETWORK_H
|
||||
|
||||
#include <exceptions/exceptions.h>
|
||||
#include <dhcpsrv/assignable_network.h>
|
||||
#include <dhcpsrv/subnet.h>
|
||||
#include <dhcpsrv/subnet_id.h>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
class SharedNetwork;
|
||||
|
||||
/// @brief Pointer to the @ref SharedNetwork object.
|
||||
typedef boost::shared_ptr<SharedNetwork> SharedNetworkPtr;
|
||||
|
||||
/// @brief Represents shared network, which groups multiple subnets.
|
||||
///
|
||||
/// Shared networks provide means for grouping multiple subnets together.
|
||||
/// There are two major use cases for such grouping:
|
||||
///
|
||||
/// - Extending available address pools to be allocated for clients on
|
||||
/// a particular link without a need to renumber.
|
||||
/// - Fulfill requirement in cable networks whereby two classes of devices
|
||||
/// are connected on the same link: cable modems and routers. Such devices
|
||||
/// must be assign addresses/prefixes from different pools based on client
|
||||
/// classification.
|
||||
///
|
||||
/// Shared networks provide similar interface like subnets, thus they both
|
||||
/// derive from the @ref Network class.
|
||||
class SharedNetwork : public AssignableNetwork {
|
||||
protected:
|
||||
|
||||
/// @brief Adds a subnet to a shared network.
|
||||
///
|
||||
/// This is a generic method for adding a new subnet to a shared network.
|
||||
///
|
||||
/// @param [out] subnets Container holding subnets for this shared network.
|
||||
/// @param subnet Pointer to a subnet being added to this shared network.
|
||||
///
|
||||
/// @tparam SubnetPtrType Type of a pointer to a subnet, i.e. Subnet4Ptr
|
||||
/// or @ref Subnet6Ptr.
|
||||
/// @tparam SubnetCollectionType Type of a container holding subnets, i.e.
|
||||
/// @ref Subnet4Collection or @ref Subnet6Collection.
|
||||
///
|
||||
/// @throw isc::BadValue if subnet is null.
|
||||
/// @throw isc::DuplicateSubnetID if a subnet with the given subnet id
|
||||
/// already exists in this shared network.
|
||||
/// @throw InvalidOperation if a subnet is already associated with some
|
||||
/// shared network.
|
||||
template<typename SubnetPtrType, typename SubnetCollectionType>
|
||||
void add(SubnetCollectionType& subnets, const SubnetPtrType& subnet) {
|
||||
// Subnet must be non-null.
|
||||
if (!subnet) {
|
||||
isc_throw(BadValue, "null pointer specified when adding a subnet"
|
||||
" to a shared network");
|
||||
}
|
||||
|
||||
// Check if a subnet with this id already exists.
|
||||
if (getSubnet<SubnetPtrType>(subnets, subnet->getID())) {
|
||||
isc_throw(DuplicateSubnetID, "attempted to add subnet with a"
|
||||
" duplicated subnet identifier " << subnet->getID());
|
||||
}
|
||||
|
||||
// Check if the subnet is already associated with some network.
|
||||
SharedNetworkPtr network;
|
||||
subnet->getSharedNetwork(network);
|
||||
if (network) {
|
||||
isc_throw(InvalidOperation, "subnet " << subnet->getID()
|
||||
<< " being added to a shared network"
|
||||
" already belongs to a shared network");
|
||||
}
|
||||
|
||||
// Add a subnet to the collection of subnets for this shared network.
|
||||
subnets.push_back(subnet);
|
||||
// Associate the subnet with this network.
|
||||
setSharedNetwork(subnet);
|
||||
}
|
||||
|
||||
/// @brief Removes a subnet from the shared network.
|
||||
///
|
||||
/// @param [out] subnets Container holding subnets for this shared network.
|
||||
/// @param subnet_id Identifier of a subnet to be removed.
|
||||
///
|
||||
/// @tparam SubnetCollectionType Type of a container holding subnets, i.e.
|
||||
/// @ref Subnet4Collection or @ref Subnet6Collection.
|
||||
///
|
||||
/// @throw BadValue if a subnet with specified identifier doesn't exist.
|
||||
template<typename SubnetCollectionType>
|
||||
void del(SubnetCollectionType& subnets, const SubnetID& subnet_id) {
|
||||
auto& index = subnets.template get<SubnetSubnetIdIndexTag>();
|
||||
auto subnet_it = index.find(subnet_id);
|
||||
if (subnet_it == index.end()) {
|
||||
isc_throw(BadValue, "unable to delete subnet " << subnet_id
|
||||
<< " from shared network. Subnet doesn't belong"
|
||||
" to this shared network");
|
||||
}
|
||||
auto subnet = *subnet_it;
|
||||
index.erase(subnet_it);
|
||||
clearSharedNetwork(subnet);
|
||||
}
|
||||
|
||||
/// @brief Returns a subnet belonging to this network for a given subnet id.
|
||||
///
|
||||
/// @param subnets Container holding subnets for this shared network.
|
||||
/// @param subnet_id Identifier of a subnet being retrieved.
|
||||
///
|
||||
/// @tparam SubnetPtrType Type of a pointer to a subnet, i.e. Subnet4Ptr
|
||||
/// or @ref Subnet6Ptr.
|
||||
/// @tparam SubnetCollectionType Type of a container holding subnets, i.e.
|
||||
/// @ref Subnet4Collection or @ref Subnet6Collection.
|
||||
///
|
||||
/// @return Pointer to the subnet or null if the subnet doesn't exist.
|
||||
template<typename SubnetPtrType, typename SubnetCollectionType>
|
||||
SubnetPtrType getSubnet(const SubnetCollectionType& subnets,
|
||||
const SubnetID& subnet_id) const {
|
||||
const auto& index = subnets.template get<SubnetSubnetIdIndexTag>();
|
||||
auto subnet_it = index.find(subnet_id);
|
||||
if (subnet_it != index.cend()) {
|
||||
return (*subnet_it);
|
||||
}
|
||||
|
||||
// Subnet not found.
|
||||
return (SubnetPtrType());
|
||||
}
|
||||
|
||||
/// @brief Retrieves next available subnet within shared network.
|
||||
///
|
||||
/// This method returns next available subnet within a shared network.
|
||||
/// The subnets are ordered and retrieved using random access index
|
||||
/// (first in/first out). The next subnet means next in turn after
|
||||
/// the current subnet, which is specified as an argument. A caller
|
||||
/// can iterate over all subnets starting from any of the subnets
|
||||
/// belonging to a shared network. This subnet is called here as
|
||||
/// a first subnet and is also specified as a method argument. When the
|
||||
/// method detects that the next available subnet is a first subnet, it
|
||||
/// returns a null pointer to indicate that there are no more subnets
|
||||
/// available.
|
||||
///
|
||||
/// The typical use case for this method is to allow DHCP server's
|
||||
/// allocation engine to walk over the available subnets within a shared
|
||||
/// network, starting from a subnet that has been selected during the
|
||||
/// "subnet selection" processing step. In some cases the allocation
|
||||
/// engine is unable to allocate resources from a selected subnet due
|
||||
/// to client classification restrictions or address shortage within
|
||||
/// its pools. It then uses this mechanism to move to another subnet
|
||||
/// belonging to the same shared network.
|
||||
///
|
||||
/// @param subnets Container holding subnets belonging to this shared
|
||||
/// network.
|
||||
/// @param first_subnet Pointer to a subnet from which the caller is
|
||||
/// iterating over subnets within shared network. This is typically a
|
||||
/// subnet selected during "subnet selection" step.
|
||||
/// @param current_subnet Pointer to a subnet for which next subnet is
|
||||
/// to be found.
|
||||
///
|
||||
/// @tparam SubnetPtrType Type of the pointer to a subnet, i.e.
|
||||
/// @ref Subnet4Ptr or @ref Subnet6Ptr.
|
||||
/// @tparam SubnetCollectionType Type of the container holding subnets, i.e.
|
||||
/// @ref Subnet4Collection or @ref Subnet6Collection.
|
||||
///
|
||||
/// @return Pointer to next subnet or null pointer if no more subnets found.
|
||||
///
|
||||
/// @throw isc::BadValue if invalid arguments specified, e.g. unable to
|
||||
/// find first or current subnet within the container.
|
||||
template<typename SubnetPtrType, typename SubnetCollectionType>
|
||||
SubnetPtrType getNextSubnet(const SubnetCollectionType& subnets,
|
||||
const SubnetPtrType& first_subnet,
|
||||
const SubnetPtrType& current_subnet) const {
|
||||
// Current subnet must not be null. The caller must explicitly set it
|
||||
// to one of the pointers that belong to this shared network, typically
|
||||
// to a selected subnet.
|
||||
if (!current_subnet) {
|
||||
isc_throw(BadValue, "null subnet specified for a shared"
|
||||
" network while searching for next subnet is this"
|
||||
" network");
|
||||
}
|
||||
|
||||
// It is ok to have a shared network without any subnets, but in this
|
||||
// case there is nothing else we can return but null pointer.
|
||||
if (subnets.empty()) {
|
||||
return (SubnetPtrType());
|
||||
}
|
||||
|
||||
// Need to retrieve an iterator to the current subnet first. The
|
||||
// subnet must exist in this container, thus we throw if the iterator
|
||||
// is not found.
|
||||
const auto& index = subnets.template get<SubnetSubnetIdIndexTag>();
|
||||
auto subnet_id_it = index.find(current_subnet->getID());
|
||||
if (subnet_id_it == index.cend()) {
|
||||
isc_throw(BadValue, "no such subnet " << current_subnet->getID()
|
||||
<< " within shared network");
|
||||
}
|
||||
|
||||
// We need to transform this iterator (by subnet id) to a random access
|
||||
// index iterator. Multi index container has a nice way of doing it.
|
||||
auto subnet_it = subnets.template project<SubnetRandomAccessIndexTag>(subnet_id_it);
|
||||
|
||||
// Step to a next subnet within random access index.
|
||||
if (++subnet_it == subnets.cend()) {
|
||||
// If we reached the end of the container, start over from the
|
||||
// beginning.
|
||||
subnet_it = subnets.cbegin();
|
||||
}
|
||||
|
||||
// Check if we have made a full circle. If we did, return a null pointer
|
||||
// to indicate that there are no more subnets.
|
||||
if ((*subnet_it)->getID() == first_subnet->getID()) {
|
||||
return (SubnetPtrType());
|
||||
}
|
||||
|
||||
// Got the next subnet, so return it.
|
||||
return (*subnet_it);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// @brief Shared network holding IPv4 subnets.
|
||||
///
|
||||
/// Specialization of the @ref SharedNetwork class for IPv4 subnets.
|
||||
class SharedNetwork4 : public SharedNetwork,
|
||||
public boost::enable_shared_from_this<SharedNetwork4> {
|
||||
public:
|
||||
|
||||
/// @brief Returns shared pointer to this network.
|
||||
///
|
||||
/// This method is required by the parent @ref AssignableNetwork class.
|
||||
///
|
||||
/// @return Shared pointer to this object.
|
||||
virtual NetworkPtr sharedFromThis();
|
||||
|
||||
/// @brief Adds IPv4 subnet to a shared network.
|
||||
///
|
||||
/// @param subnet Pointer to a subnet being added to this shared network.
|
||||
///
|
||||
/// @throw isc::BadValue if subnet is null.
|
||||
/// @throw isc::DuplicateSubnetID if a subnet with the given subnet id
|
||||
/// already exists in this shared network.
|
||||
/// @throw InvalidOperation if a subnet is already associated with some
|
||||
/// shared network.
|
||||
void add(const Subnet4Ptr& subnet);
|
||||
|
||||
/// @brief Removes subnet from a shared network.
|
||||
///
|
||||
/// @param subnet_id Identifier of a subnet to be removed.
|
||||
///
|
||||
/// @throw BadValue When specified subnet doesn't exist.
|
||||
void del(const SubnetID& subnet_id);
|
||||
|
||||
/// @brief Returns a pointer to the collection of subnets within this
|
||||
/// shared network.
|
||||
const Subnet4Collection* getAllSubnets() const {
|
||||
return (&subnets_);
|
||||
}
|
||||
|
||||
/// @brief Returns a subnet for a specified subnet id.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
///
|
||||
/// @return Shared pointer to a subnet using this id or null pointer
|
||||
/// if such subnet doesn't exist within shared network.
|
||||
Subnet4Ptr getSubnet(const SubnetID& subnet_id) const;
|
||||
|
||||
/// @brief Retrieves next available IPv4 subnet within shared network.
|
||||
///
|
||||
/// See documentation for @ref SharedNetwork::getNextSubnet.
|
||||
///
|
||||
/// @param first_subnet Pointer to a subnet from which the caller is
|
||||
/// iterating over subnets within shared network. This is typically a
|
||||
/// subnet selected during "subnet selection" step.
|
||||
/// @param current_subnet Pointer to a subnet for which next subnet is
|
||||
/// to be found.
|
||||
///
|
||||
/// @return Pointer to next subnet or null pointer if no more subnets found.
|
||||
///
|
||||
/// @throw isc::BadValue if invalid arguments specified, e.g. unable to
|
||||
/// find first or current subnet within shared network.
|
||||
Subnet4Ptr getNextSubnet(const Subnet4Ptr& first_subnet,
|
||||
const Subnet4Ptr& current_subnet) const;
|
||||
|
||||
private:
|
||||
|
||||
/// @brief Collection of IPv4 subnets within shared network.
|
||||
Subnet4Collection subnets_;
|
||||
|
||||
};
|
||||
|
||||
/// @brief Pointer to @ref SharedNetwork4 object.
|
||||
typedef boost::shared_ptr<SharedNetwork4> SharedNetwork4Ptr;
|
||||
|
||||
/// @brief Shared network holding IPv6 subnets.
|
||||
///
|
||||
/// Specialization of the @ref SharedNetwork class for IPv6 subnets.
|
||||
class SharedNetwork6 : public SharedNetwork,
|
||||
public boost::enable_shared_from_this<SharedNetwork6> {
|
||||
public:
|
||||
|
||||
/// @brief Returns shared pointer to this network.
|
||||
///
|
||||
/// This method is required by the parent @ref AssignableNetwork class.
|
||||
///
|
||||
/// @return Shared pointer to this object.
|
||||
virtual NetworkPtr sharedFromThis();
|
||||
|
||||
/// @brief Adds IPv6 subnet to a shared network.
|
||||
///
|
||||
/// @param subnet Pointer to a subnet being added to this shared network.
|
||||
///
|
||||
/// @throw isc::BadValue if subnet is null.
|
||||
/// @throw isc::DuplicateSubnetID if a subnet with the given subnet id
|
||||
/// already exists in this shared network.
|
||||
/// @throw InvalidOperation if a subnet is already associated with some
|
||||
/// shared network.
|
||||
void add(const Subnet6Ptr& subnet);
|
||||
|
||||
/// @brief Removes subnet from a shared network.
|
||||
///
|
||||
/// @param subnet_id Identifier of a subnet to be removed.
|
||||
///
|
||||
/// @throw BadValue When specified subnet doesn't exist.
|
||||
void del(const SubnetID& subnet_id);
|
||||
|
||||
/// @brief Returns a pointer to the collection of subnets within this
|
||||
/// shared network.
|
||||
const Subnet6Collection* getAllSubnets() const {
|
||||
return (&subnets_);
|
||||
}
|
||||
|
||||
/// @brief Returns a subnet for a specified subnet id.
|
||||
///
|
||||
/// @param subnet_id Subnet identifier.
|
||||
///
|
||||
/// @return Shared pointer to a subnet using this id or null pointer
|
||||
/// if such subnet doesn't exist within shared network.
|
||||
Subnet6Ptr getSubnet(const SubnetID& subnet_id) const;
|
||||
|
||||
/// @brief Retrieves next available IPv6 subnet within shared network.
|
||||
///
|
||||
/// See documentation for @ref SharedNetwork::getNextSubnet.
|
||||
///
|
||||
/// @param first_subnet Pointer to a subnet from which the caller is
|
||||
/// iterating over subnets within shared network. This is typically a
|
||||
/// subnet selected during "subnet selection" step.
|
||||
/// @param current_subnet Pointer to a subnet for which next subnet is
|
||||
/// to be found.
|
||||
///
|
||||
/// @return Pointer to next subnet or null pointer if no more subnets found.
|
||||
///
|
||||
/// @throw isc::BadValue if invalid arguments specified, e.g. unable to
|
||||
/// find first or current subnet within shared network.
|
||||
Subnet6Ptr getNextSubnet(const Subnet6Ptr& first_subnet,
|
||||
const Subnet6Ptr& current_subnet) const;
|
||||
|
||||
private:
|
||||
|
||||
/// @brief Collection of IPv6 subnets within shared network.
|
||||
Subnet6Collection subnets_;
|
||||
};
|
||||
|
||||
/// @brief Pointer to @ref SharedNetwork6 object.
|
||||
typedef boost::shared_ptr<SharedNetwork6> SharedNetwork6Ptr;
|
||||
|
||||
} // end of namespace isc::dhcp
|
||||
} // end of namespace isc
|
||||
|
||||
#endif // SHARED_NETWORK_H
|
@@ -354,16 +354,6 @@ Subnet::delPools(Lease::Type type) {
|
||||
getPoolsWritable(type).clear();
|
||||
}
|
||||
|
||||
void
|
||||
Subnet::setIface(const std::string& iface_name) {
|
||||
iface_ = iface_name;
|
||||
}
|
||||
|
||||
std::string
|
||||
Subnet::getIface() const {
|
||||
return (iface_);
|
||||
}
|
||||
|
||||
bool
|
||||
Subnet::inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const {
|
||||
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include <dhcp/option.h>
|
||||
#include <dhcp/classify.h>
|
||||
#include <dhcp/option_space_container.h>
|
||||
#include <dhcpsrv/assignable_network.h>
|
||||
#include <dhcpsrv/cfg_option.h>
|
||||
#include <dhcpsrv/cfg_4o6.h>
|
||||
#include <dhcpsrv/lease.h>
|
||||
@@ -24,12 +25,18 @@
|
||||
#include <boost/multi_index/ordered_index.hpp>
|
||||
#include <boost/multi_index/random_access_index.hpp>
|
||||
#include <boost/multi_index_container.hpp>
|
||||
#include <boost/pointer_cast.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
namespace isc {
|
||||
namespace dhcp {
|
||||
|
||||
class Subnet {
|
||||
class Subnet : public Network {
|
||||
|
||||
// Assignable network is our friend to allow it to call
|
||||
// @ref Subnet::setSharedNetwork private function.
|
||||
friend class AssignableNetwork;
|
||||
|
||||
public:
|
||||
|
||||
/// @brief Holds optional information about relay.
|
||||
@@ -233,16 +240,6 @@ public:
|
||||
/// @param type type of the lease
|
||||
uint64_t getPoolCapacity(Lease::Type type) const;
|
||||
|
||||
/// @brief Sets name of the network interface for directly attached networks
|
||||
///
|
||||
/// @param iface_name name of the interface
|
||||
void setIface(const std::string& iface_name);
|
||||
|
||||
/// @brief Network interface name used to reach subnet (or "" for remote
|
||||
/// subnets)
|
||||
/// @return network interface name for directly attached subnets or ""
|
||||
std::string getIface() const;
|
||||
|
||||
/// @brief Returns textual representation of the subnet (e.g.
|
||||
/// "2001:db8::/64")
|
||||
///
|
||||
@@ -349,6 +346,41 @@ public:
|
||||
host_reservation_mode_ = mode;
|
||||
}
|
||||
|
||||
/// @brief Retrieves pointer to a shared network associated with a subnet.
|
||||
///
|
||||
/// By implementing it as a template function we overcome a need to
|
||||
/// include shared_network.h header file to specify return type explicitly.
|
||||
/// The header can't be included because it would cause circular dependency
|
||||
/// between subnet.h and shared_network.h.
|
||||
///
|
||||
/// This method uses an argument to hold a return value to allow the compiler
|
||||
/// to infer the return type without a need to call this function with an
|
||||
/// explicit return type as template argument.
|
||||
///
|
||||
/// @param [out] shared_network Pointer to the shared network where returned
|
||||
/// value should be assigned.
|
||||
///
|
||||
/// @tparam Type of the shared network, i.e. @ref SharedNetwork4 or a
|
||||
/// @ref SharedNetwork6.
|
||||
template<typename SharedNetworkPtrType>
|
||||
void getSharedNetwork(SharedNetworkPtrType& shared_network) const {
|
||||
shared_network = boost::dynamic_pointer_cast<
|
||||
typename SharedNetworkPtrType::element_type>(shared_network_);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// @brief Assigns shared network to a subnet.
|
||||
///
|
||||
/// This method replaces any shared network associated with a subnet with
|
||||
/// a new shared network.
|
||||
///
|
||||
/// @param shared_network Pointer to a new shared network to be associated
|
||||
/// with the subnet.
|
||||
void setSharedNetwork(const NetworkPtr& shared_network) {
|
||||
shared_network_ = shared_network;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @brief Returns all pools (non-const variant)
|
||||
///
|
||||
@@ -518,10 +550,11 @@ protected:
|
||||
///
|
||||
/// See @ref HRMode type for details.
|
||||
HRMode host_reservation_mode_;
|
||||
private:
|
||||
|
||||
/// @brief Pointer to the option data configuration for this subnet.
|
||||
CfgOptionPtr cfg_option_;
|
||||
|
||||
NetworkPtr shared_network_;
|
||||
};
|
||||
|
||||
/// @brief A generic pointer to either Subnet4 or Subnet6 object
|
||||
|
@@ -121,6 +121,7 @@ if HAVE_CQL
|
||||
libdhcpsrv_unittests_SOURCES += cql_lease_mgr_unittest.cc
|
||||
endif
|
||||
libdhcpsrv_unittests_SOURCES += pool_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += shared_network_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += srv_config_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += subnet_unittest.cc
|
||||
libdhcpsrv_unittests_SOURCES += test_get_callout_handle.cc test_get_callout_handle.h
|
||||
|
172
src/lib/dhcpsrv/tests/shared_network_unittest.cc
Normal file
172
src/lib/dhcpsrv/tests/shared_network_unittest.cc
Normal file
@@ -0,0 +1,172 @@
|
||||
// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
#include <asiolink/io_address.h>
|
||||
#include <dhcpsrv/shared_network.h>
|
||||
#include <dhcpsrv/subnet.h>
|
||||
#include <dhcpsrv/subnet_id.h>
|
||||
#include <dhcpsrv/triplet.h>
|
||||
#include <exceptions/exceptions.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
using namespace isc;
|
||||
using namespace isc::asiolink;
|
||||
using namespace isc::dhcp;
|
||||
|
||||
namespace {
|
||||
|
||||
// This test verifies that an IPv4 subnet can be added to a shared network.
|
||||
// It also verifies that two subnets with the same ID can't be added to
|
||||
// a shared network and that a single subnet can't be added to two different
|
||||
// shared subnets.
|
||||
TEST(SharedNetwork4Test, addSubnet4) {
|
||||
// First, create a network.
|
||||
SharedNetwork4Ptr network(new SharedNetwork4());
|
||||
|
||||
// Try to add null pointer. It should throw.
|
||||
Subnet4Ptr subnet;
|
||||
ASSERT_THROW(network->add(subnet), BadValue);
|
||||
|
||||
// Create a valid subnet. It should now be added successfully.
|
||||
subnet.reset(new Subnet4(IOAddress("10.0.0.0"), 8, 10, 20, 30,
|
||||
SubnetID(15)));
|
||||
ASSERT_NO_THROW(network->add(subnet));
|
||||
ASSERT_EQ(1, network->getAllSubnets()->size());
|
||||
|
||||
// Retrieve the subnet from the network and make sure it is returned
|
||||
// as expected.
|
||||
Subnet4Ptr returned_subnet = network->getAllSubnets()->front();
|
||||
ASSERT_TRUE(returned_subnet);
|
||||
EXPECT_EQ(subnet->getID(), returned_subnet->getID());
|
||||
SharedNetwork4Ptr network1;
|
||||
subnet->getSharedNetwork(network1);
|
||||
ASSERT_TRUE(network1);
|
||||
EXPECT_TRUE(network1 == network);
|
||||
|
||||
// Create another subnet with the same ID. Adding a network with the
|
||||
// same ID should cause an error.
|
||||
Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.0"), 24, 10, 20, 30,
|
||||
SubnetID(15)));
|
||||
ASSERT_THROW(network->add(subnet), DuplicateSubnetID);
|
||||
|
||||
// Create another network and try to add a subnet to it. It should fail
|
||||
// because the subnet is already associated with the first network.
|
||||
SharedNetwork4Ptr network2(new SharedNetwork4());
|
||||
ASSERT_THROW(network2->add(subnet), InvalidOperation);
|
||||
}
|
||||
|
||||
// This test verifies that it is possible to remove a specified subnet.
|
||||
TEST(SharedNetwork4Test, delSubnet4) {
|
||||
// Create two subnets and add them to the shared network.
|
||||
Subnet4Ptr subnet1(new Subnet4(IOAddress("10.0.0.0"), 8, 10, 20, 30,
|
||||
SubnetID(1)));
|
||||
Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.0"), 24, 10, 20, 30,
|
||||
SubnetID(2)));
|
||||
|
||||
SharedNetwork4Ptr network(new SharedNetwork4());
|
||||
ASSERT_NO_THROW(network->add(subnet1));
|
||||
ASSERT_NO_THROW(network->add(subnet2));
|
||||
|
||||
// Make sure they have been added successfully.
|
||||
ASSERT_EQ(2, network->getAllSubnets()->size());
|
||||
|
||||
// Try to remove a subnet that doesn't exist in this shared network.
|
||||
// It should cause an error.
|
||||
ASSERT_THROW(network->del(SubnetID(5)), BadValue);
|
||||
|
||||
// Now delete the subnet that exists.
|
||||
ASSERT_NO_THROW(network->del(subnet1->getID()));
|
||||
// We should be left with only one subnet.
|
||||
ASSERT_EQ(1, network->getAllSubnets()->size());
|
||||
Subnet4Ptr subnet_returned = network->getAllSubnets()->front();
|
||||
ASSERT_TRUE(subnet_returned);
|
||||
EXPECT_EQ(subnet2->getID(), subnet_returned->getID());
|
||||
|
||||
// Check that shared network has been cleared for the removed subnet.
|
||||
SharedNetwork4Ptr network1;
|
||||
subnet1->getSharedNetwork(network1);
|
||||
EXPECT_FALSE(network1);
|
||||
|
||||
// Remove another subnet and make sure there are no subnets left.
|
||||
ASSERT_NO_THROW(network->del(subnet2->getID()));
|
||||
EXPECT_EQ(0, network->getAllSubnets()->size());
|
||||
|
||||
// The network pointer should be cleared for this second subnet too.
|
||||
SharedNetwork4Ptr network2;
|
||||
subnet1->getSharedNetwork(network2);
|
||||
EXPECT_FALSE(network2);
|
||||
}
|
||||
|
||||
// This test verifies that it is possible to iterate over the subnets
|
||||
// associated with a particular shared network.
|
||||
TEST(SharedNetwork4Test, getNextSubnet) {
|
||||
SharedNetwork4Ptr network(new SharedNetwork4());
|
||||
|
||||
// Create three subnets.
|
||||
Subnet4Ptr subnet1(new Subnet4(IOAddress("10.0.0.0"), 8, 10, 20, 30,
|
||||
SubnetID(1)));
|
||||
Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.0"), 24, 10, 20, 30,
|
||||
SubnetID(2)));
|
||||
Subnet4Ptr subnet3(new Subnet4(IOAddress("172.16.25.0"), 24, 10, 20, 30,
|
||||
SubnetID(3)));
|
||||
std::vector<Subnet4Ptr> subnets;
|
||||
subnets.push_back(subnet1);
|
||||
subnets.push_back(subnet2);
|
||||
subnets.push_back(subnet3);
|
||||
|
||||
// Subnets have unique IDs so they should successfully be added to the
|
||||
// network.
|
||||
for (auto i = 0; i < subnets.size(); ++i) {
|
||||
ASSERT_NO_THROW(network->add(subnets[i]))
|
||||
<< "failed to add subnet with id " << subnets[i]->getID()
|
||||
<< " to shared network";
|
||||
}
|
||||
|
||||
// Collect networks associated with our subnets in the vector.
|
||||
std::vector<SharedNetwork4Ptr> networks;
|
||||
for (auto i = 0; i < subnets.size(); ++i) {
|
||||
SharedNetwork4Ptr network;
|
||||
subnets[i]->getSharedNetwork(network);
|
||||
ASSERT_TRUE(network) << "failed to retrieve shared network for a"
|
||||
<< " subnet id " << subnets[i]->getID();
|
||||
networks.push_back(network);
|
||||
}
|
||||
|
||||
// All subnets should be associated with the same network.
|
||||
for (auto i = 1; i < networks.size(); ++i) {
|
||||
EXPECT_TRUE(networks[0] == networks[i]);
|
||||
}
|
||||
|
||||
// Perform the test 3 times where each subnet belonging to the shared
|
||||
// network is treated as a "first" subnet in the call to getNextSubnet.
|
||||
for (auto i = 0; i < subnets.size(); ++i) {
|
||||
Subnet4Ptr s = subnets[i];
|
||||
|
||||
// Iterate over the subnets starting from the subnet with index i.
|
||||
for (auto j = 0; j < subnets.size(); ++j) {
|
||||
// Get next subnet (following the one currently in s).
|
||||
s = networks[0]->getNextSubnet(subnets[i], s);
|
||||
// The last iteration should return empty pointer to indicate end of
|
||||
// the subnets within shared network. If we're not at last iteration
|
||||
// check that the subnet identifier of the returned subnet is valid.
|
||||
if (j < subnets.size() - 1) {
|
||||
ASSERT_TRUE(s) << "retrieving next subnet failed for pair of"
|
||||
" indexes (i, j) = (" << i << ", " << j << ")";
|
||||
const auto expected_subnet_id = (i + j + 1) % subnets.size() + 1;
|
||||
EXPECT_EQ(expected_subnet_id, s->getID());
|
||||
} else {
|
||||
// Null subnet returned for a last iteration.
|
||||
ASSERT_FALSE(s) << "expected null pointer to be returned as"
|
||||
" next subnet for pair of indexes (i, j) = ("
|
||||
<< i << ", " << j << ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end of anonymous namespace
|
Reference in New Issue
Block a user