Browse Source

[4308] Implemented subnet selection based on interface name.

Tomek Mrugalski 9 years ago
parent
commit
7a4c274d2e
2 changed files with 63 additions and 1 deletions
  1. 39 1
      src/lib/dhcpsrv/cfg_subnets4.cc
  2. 24 0
      src/lib/dhcpsrv/cfg_subnets4.h

+ 39 - 1
src/lib/dhcpsrv/cfg_subnets4.cc

@@ -138,7 +138,16 @@ 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);
+        }
     }
 
     // Unable to find a suitable address to use for subnet selection.
@@ -152,6 +161,34 @@ CfgSubnets4::selectSubnet(const SubnetSelector& selector) const {
 }
 
 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;
+        }
+
+        // Eliminate those subnets that do not meet client class criteria.
+        if ((*subnet)->clientSupported(client_classes)) {
+            return (*subnet);
+        }
+    }
+
+    // Failed to find a subnet.
+    return (Subnet4Ptr());
+}
+
+Subnet4Ptr
 CfgSubnets4::selectSubnet(const IOAddress& address,
                  const ClientClasses& client_classes) const {
     for (Subnet4Collection::const_iterator subnet = subnets_.begin();
@@ -172,6 +209,7 @@ CfgSubnets4::selectSubnet(const IOAddress& address,
     return (Subnet4Ptr());
 }
 
+
 bool
 CfgSubnets4::isDuplicate(const Subnet4& subnet) const {
     for (Subnet4Collection::const_iterator subnet_it = subnets_.begin();

+ 24 - 0
src/lib/dhcpsrv/cfg_subnets4.h

@@ -120,6 +120,30 @@ public:
                             const ClientClasses& client_classes
                             = ClientClasses()) const;
 
+    /// @brief Returns pointer to a subnet if provided interface name matches.
+    ///
+    /// This method returns a pointer to the subnet if the interface name passed
+    /// in parameter matches that of a subnet. This is mainly used for matching
+    /// local incoming traffic, even when the addresses on local interfaces do
+    /// not match 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: