Commit 7c74ecdb authored by Tomek Mrugalski's avatar Tomek Mrugalski 🛰
Browse files

[master] Merge branch 'trac4308' (interface selection based on name)

parents ae890cc8 da0a231b
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2016 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
......@@ -100,7 +100,7 @@ CfgSubnets4::selectSubnet(const SubnetSelector& selector) const {
continue;
}
// Eliminate those subnets that do not meet client class criteria.
// If a subnet meets the client class criteria return it.
if ((*subnet)->clientSupported(selector.client_classes_)) {
return (*subnet);
}
......@@ -138,7 +138,20 @@ CfgSubnets4::selectSubnet(const SubnetSelector& selector) const {
<< " doesn't exist and therefore it is impossible"
" to find a suitable subnet for its IPv4 address");
}
iface->getAddress4(address);
// Attempt to select subnet based on the interface name.
Subnet4Ptr subnet = selectSubnet(selector.iface_name_,
selector.client_classes_);
// If it matches - great. If not, we'll try to use a different
// selection criteria below.
if (subnet) {
return (subnet);
} else {
// Let's try to get an address from the local interface and
// try to match it to defined subnet.
iface->getAddress4(address);
}
}
// Unable to find a suitable address to use for subnet selection.
......@@ -151,6 +164,38 @@ CfgSubnets4::selectSubnet(const SubnetSelector& selector) const {
return (selectSubnet(address, selector.client_classes_));
}
Subnet4Ptr
CfgSubnets4::selectSubnet(const std::string& iface,
const ClientClasses& client_classes) const {
for (Subnet4Collection::const_iterator subnet = subnets_.begin();
subnet != subnets_.end(); ++subnet) {
// If there's no interface specified for this subnet, proceed to
// the next subnet.
if ((*subnet)->getIface().empty()) {
continue;
}
// If it's specified, but does not match, proceed to the next
// subnet.
if ((*subnet)->getIface() != iface) {
continue;
}
// If a subnet meets the client class criteria return it.
if ((*subnet)->clientSupported(client_classes)) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE,
DHCPSRV_CFGMGR_SUBNET4_IFACE)
.arg((*subnet)->toText())
.arg(iface);
return (*subnet);
}
}
// Failed to find a subnet.
return (Subnet4Ptr());
}
Subnet4Ptr
CfgSubnets4::selectSubnet(const IOAddress& address,
const ClientClasses& client_classes) const {
......@@ -162,8 +207,11 @@ CfgSubnets4::selectSubnet(const IOAddress& address,
continue;
}
// Eliminate those subnets that do not meet client class criteria.
// If a subnet meets the client class criteria return it.
if ((*subnet)->clientSupported(client_classes)) {
LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_SUBNET4_ADDR)
.arg((*subnet)->toText())
.arg(address.toText());
return (*subnet);
}
}
......
// Copyright (C) 2014-2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2016 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
......@@ -47,7 +47,7 @@ public:
return (&subnets_);
}
/// @brief Returns pointer to the selected subnet.
/// @brief Returns a pointer to the selected subnet.
///
/// This method tries to retrieve the subnet for the client using various
/// parameters extracted from the client's message using the following
......@@ -96,7 +96,7 @@ public:
/// or they are insufficient to select a subnet.
Subnet4Ptr selectSubnet(const SubnetSelector& selector) const;
/// @brief Returns pointer to a subnet if provided address is in its range.
/// @brief Returns a pointer to a subnet if provided address is in its range.
///
/// This method returns a pointer to the subnet if the address passed in
/// parameter is in range with this subnet. This is mainly used for unit
......@@ -120,6 +120,30 @@ public:
const ClientClasses& client_classes
= ClientClasses()) const;
/// @brief Returns a pointer to a subnet if provided interface name matches.
///
/// This method returns a pointer to the subnet if the interface name passed
/// in parameter iface matches that of a subnet. This is mainly used for matching
/// local incoming traffic, even when the addresses on local interfaces do
/// not match a subnet definition. This method is also called by the
/// @c selectSubnet(SubnetSelector).
///
/// @todo This method requires performance improvement! It currently
/// iterates over all existing subnets to find the one which fulfils
/// the search criteria. The subnet storage is implemented as a simple
/// STL vector which precludes fast searches using specific keys.
/// Hence, full scan is required. To improve the search performance a
/// different container type is required, e.g. multi-index container,
/// or something of a similar functionality.
///
/// @param iface name of the interface to be matched.
/// @param client_classes Optional parameter specifying the classes that
/// the client belongs to.
///
/// @return Pointer to the selected subnet or NULL if no subnet found.
Subnet4Ptr selectSubnet(const std::string& iface,
const ClientClasses& client_classes) const;
/// @brief Attempts to do subnet selection based on DHCP4o6 information
///
/// The algorithm implemented is as follows:
......
......@@ -102,6 +102,19 @@ This is a debug message reporting that the DHCP configuration manager has
returned the specified IPv4 subnet when given the address hint specified
as the address is within the subnet.
% DHCPSRV_CFGMGR_SUBNET4_ADDR selected subnet %1 for packet received by matching address %2
This is a debug message reporting that the DHCP configuration manager
has returned the specified IPv4 subnet for a received packet. This particular
subnet was selected, because an IPv4 address was matched which belonged to that
subnet.
% DHCPSRV_CFGMGR_SUBNET4_IFACE selected subnet %1 for packet received over interface %2
This is a debug message reporting that the DHCP configuration manager
has returned the specified IPv4 subnet for a packet received over
the given interface. This particular subnet was selected, because it
was specified as being directly reachable over the given interface. (see
'interface' parameter in the subnet4 definition).
% DHCPSRV_CFGMGR_SUBNET4_RELAY selected subnet %1, because of matching relay addr %2
This is a debug message reporting that the DHCP configuration manager has
returned the specified IPv4 subnet, because detected relay agent address
......
......@@ -61,6 +61,42 @@ TEST(CfgSubnets4Test, selectSubnetByCiaddr) {
EXPECT_FALSE(cfg.selectSubnet(selector));
}
// This test verifies that it is possible to select a subnet by
// matching an interface name.
TEST(CfgSubnets4Test, selectSubnetByIface) {
// The IfaceMgrTestConfig object initializes fake interfaces:
// eth0, eth1 and lo on the configuration manager. The CfgSubnets4
// object uses interface names to select the appropriate subnet.
IfaceMgrTestConfig config(true);
CfgSubnets4 cfg;
// Create 3 subnets.
Subnet4Ptr subnet1(new Subnet4(IOAddress("192.0.2.0"), 26, 1, 2, 3));
Subnet4Ptr subnet2(new Subnet4(IOAddress("192.0.2.64"), 26, 1, 2, 3));
Subnet4Ptr subnet3(new Subnet4(IOAddress("192.0.2.128"), 26, 1, 2, 3));
// No interface defined for subnet1
subnet2->setIface("lo");
subnet3->setIface("eth1");
cfg.add(subnet1);
cfg.add(subnet2);
cfg.add(subnet3);
// Make sure that initially the subnets don't exist.
SubnetSelector selector;
// Set an interface to a name that is not defined in the config.
// Subnet selection should fail.
selector.iface_name_ = "eth0";
ASSERT_FALSE(cfg.selectSubnet(selector));
// Now select an interface name that matches. Selection should succeed
// and return subnet3.
selector.iface_name_ = "eth1";
Subnet4Ptr selected = cfg.selectSubnet(selector);
ASSERT_TRUE(selected);
EXPECT_EQ(subnet3, selected);
}
// This test verifies that when the classification information is specified for
// subnets, the proper subnets are returned by the subnet configuration.
......
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