Browse Source

[5305] Moved common parameters from Subnet to Network.

Marcin Siodelski 7 years ago
parent
commit
c5e695d31d
4 changed files with 265 additions and 241 deletions
  1. 51 0
      src/lib/dhcpsrv/network.cc
  2. 206 1
      src/lib/dhcpsrv/network.h
  3. 8 58
      src/lib/dhcpsrv/subnet.cc
  4. 0 182
      src/lib/dhcpsrv/subnet.h

+ 51 - 0
src/lib/dhcpsrv/network.cc

@@ -11,6 +11,29 @@ using namespace isc::data;
 namespace isc {
 namespace dhcp {
 
+bool
+Network::clientSupported(const isc::dhcp::ClientClasses& classes) const {
+    if (white_list_.empty()) {
+        // There is no class defined for this network, so we do
+        // support everyone.
+        return (true);
+    }
+
+    for (ClientClasses::const_iterator it = white_list_.begin();
+         it != white_list_.end(); ++it) {
+        if (classes.contains(*it)) {
+            return (true);
+        }
+    }
+
+    return (false);
+}
+
+void
+Network::allowClientClass(const isc::dhcp::ClientClass& class_name) {
+    white_list_.insert(class_name);
+}
+
 ElementPtr
 Network::toElement() const {
     ElementPtr map = Element::createMap();
@@ -21,6 +44,34 @@ Network::toElement() const {
         map->set("interface", Element::create(iface));
     }
 
+    // Set relay info
+    const RelayInfo& relay_info = getRelayInfo();
+    ElementPtr relay = Element::createMap();
+    relay->set("ip-address", Element::create(relay_info.addr_.toText()));
+    map->set("relay", relay);
+
+    // Set client-class
+    const ClientClasses& cclasses = getClientClasses();
+    if (cclasses.size() > 1) {
+        isc_throw(ToElementError, "client-class has too many items: "
+                  << cclasses.size());
+    } else if (!cclasses.empty()) {
+        map->set("client-class", Element::create(*cclasses.cbegin()));
+    }
+
+    // Set renew-timer
+    map->set("renew-timer",
+             Element::create(static_cast<long long>
+                                 (getT1().get())));
+    // Set rebind-timer
+    map->set("rebind-timer",
+             Element::create(static_cast<long long>
+                                 (getT2().get())));
+    // Set valid-lifetime
+    map->set("valid-lifetime",
+             Element::create(static_cast<long long>
+                                 (getValid().get())));
+
     // Set options
     ConstCfgOptionPtr opts = getCfgOption();
     map->set("option-data", opts->toElement());

+ 206 - 1
src/lib/dhcpsrv/network.h

@@ -7,12 +7,16 @@
 #ifndef NETWORK_H
 #define NETWORK_H
 
+#include <asiolink/io_address.h>
 #include <cc/cfg_to_element.h>
 #include <cc/data.h>
+#include <dhcp/classify.h>
 #include <dhcpsrv/cfg_option.h>
 #include <dhcpsrv/cfg_4o6.h>
+#include <dhcpsrv/triplet.h>
 #include <boost/shared_ptr.hpp>
 #include <boost/weak_ptr.hpp>
+#include <cstdint>
 #include <string>
 
 namespace isc {
@@ -38,9 +42,52 @@ namespace dhcp {
 class Network : public data::CfgToElement {
 public:
 
+    /// @brief Holds optional information about relay.
+    ///
+    /// In some cases it is beneficial to have additional information about
+    /// a relay configured in the subnet. For now, the structure holds only
+    /// IP address, but there may potentially be additional parameters added
+    /// later, e.g. relay interface-id or relay-id.
+    struct RelayInfo {
+
+        /// @brief default and the only constructor
+        ///
+        /// @param addr an IP address of the relay (may be :: or 0.0.0.0)
+        RelayInfo(const isc::asiolink::IOAddress& addr);
+
+        /// @brief IP address of the relay
+        isc::asiolink::IOAddress addr_;
+    };
+
+    /// @brief Specifies allowed host reservation mode.
+    ///
+    typedef enum  {
+
+        /// None - host reservation is disabled. No reservation types
+        /// are allowed.
+        HR_DISABLED,
+
+        /// Only out-of-pool reservations is allowed. This mode
+        /// allows AllocEngine to skip reservation checks when
+        /// dealing with with addresses that are in pool.
+        HR_OUT_OF_POOL,
+
+        /// Both out-of-pool and in-pool reservations are allowed. This is the
+        /// most flexible mode, where sysadmin have biggest liberty. However,
+        /// there is a non-trivial performance penalty for it, as the
+        /// AllocEngine code has to check whether there are reservations, even
+        /// when dealing with reservations from within the dynamic pools.
+        HR_ALL
+    } HRMode;
+
+    /// Pointer to the RelayInfo structure
+    typedef boost::shared_ptr<Network::RelayInfo> RelayInfoPtr;
+
     /// @brief Constructor.
     Network()
-        : iface_name_(), cfg_option_(new CfgOption()) {
+        : iface_name_(), relay_(asiolink::IOAddress::IPV4_ZERO_ADDRESS()),
+          white_list_(), t1_(0), t2_(0), valid_(0),
+          host_reservation_mode_(HR_ALL), cfg_option_(new CfgOption()) {
     }
 
     /// @brief Virtual destructor.
@@ -68,6 +115,133 @@ public:
         return (iface_name_);
     };
 
+    /// @brief Sets information about relay
+    ///
+    /// In some situations where there are shared subnets (i.e. two different
+    /// subnets are available on the same physical link), there is only one
+    /// relay that handles incoming requests from clients. In such a case,
+    /// the usual subnet selection criteria based on relay belonging to the
+    /// subnet being selected are no longer sufficient and we need to explicitly
+    /// specify a relay. One notable example of such uncommon, but valid
+    /// scenario is a cable network, where there is only one CMTS (one relay),
+    /// but there are 2 distinct subnets behind it: one for cable modems
+    /// and another one for CPEs and other user equipment behind modems.
+    /// From manageability perspective, it is essential that modems get addresses
+    /// from different subnet, so users won't tinker with their modems.
+    ///
+    /// Setting this parameter is not needed in most deployments.
+    /// This structure holds IP address only for now, but it is expected to
+    /// be extended in the future.
+    ///
+    /// @param relay structure that contains relay information
+    void setRelayInfo(const RelayInfo& relay) {
+        relay_ = relay;
+    }
+
+    /// @brief Returns const reference to relay information
+    ///
+    /// @note The returned reference is only valid as long as the object
+    /// returned it is valid.
+    ///
+    /// @return const reference to the relay information
+    const RelayInfo& getRelayInfo() const {
+        return (relay_);
+    }
+
+    /// @brief Checks whether this network supports client that belongs to
+    /// specified classes.
+    ///
+    /// This method checks whether a client that belongs to given classes can
+    /// use this network. For example, if this class is reserved for client
+    /// class "foo" and the client belongs to classes "foo", "bar" and "baz",
+    /// it is supported. On the other hand, client belonging to classes
+    /// "foobar" and "zyxxy" is not supported.
+    ///
+    /// @todo: Currently the logic is simple: client is supported if it belongs
+    /// to any class mentioned in white_list_. We will eventually need a
+    /// way to specify more fancy logic (e.g. to meet all classes, not just
+    /// any)
+    ///
+    /// @param client_classes list of all classes the client belongs to
+    /// @return true if client can be supported, false otherwise
+    bool
+    clientSupported(const isc::dhcp::ClientClasses& client_classes) const;
+
+    /// @brief Adds class class_name to the list of supported classes
+    ///
+    /// Also see explanation note in @ref white_list_.
+    ///
+    /// @param class_name client class to be supported by this subnet
+    void allowClientClass(const isc::dhcp::ClientClass& class_name);
+
+    /// @brief returns the client class white list
+    ///
+    /// @note The returned reference is only valid as long as the object
+    /// returned it is valid.
+    ///
+    /// @return client classes @ref white_list_
+    const isc::dhcp::ClientClasses& getClientClasses() const {
+        return (white_list_);
+    }
+
+    /// @brief Return valid-lifetime for addresses in that prefix
+    Triplet<uint32_t> getValid() const {
+        return (valid_);
+    }
+
+    /// @brief Sets new valid lifetime for a network.
+    ///
+    /// @param valid New valid lifetime in seconds.
+    void setValid(const Triplet<uint32_t>& valid) {
+        valid_ = valid;
+    }
+
+    /// @brief Returns T1 (renew timer), expressed in seconds
+    Triplet<uint32_t> getT1() const {
+        return (t1_);
+    }
+
+    /// @brief Sets new renew timer for a network.
+    ///
+    /// @param t1 New renew timer value in seconds.
+    void setT1(const Triplet<uint32_t>& t1) {
+        t1_ = t1;
+    }
+
+    /// @brief Returns T2 (rebind timer), expressed in seconds
+    Triplet<uint32_t> getT2() const {
+        return (t2_);
+    }
+
+    /// @brief Sets new rebind timer for a network.
+    ///
+    /// @param t2 New rebind timer value in seconds.
+    void setT2(const Triplet<uint32_t>& t2) {
+        t2_ = t2;
+    }
+
+    /// @brief Specifies what type of Host Reservations are supported.
+    ///
+    /// Host reservations may be either in-pool (they reserve an address that
+    /// is in the dynamic pool) or out-of-pool (they reserve an address that is
+    /// not in the dynamic pool). HR may also be completely disabled for
+    /// performance reasons.
+    ///
+    /// @return whether in-pool host reservations are allowed.
+    HRMode
+    getHostReservationMode() const {
+        return (host_reservation_mode_);
+    }
+
+    /// @brief Sets host reservation mode.
+    ///
+    /// See @ref getHostReservationMode for details.
+    ///
+    /// @param mode mode to be set
+    void setHostReservationMode(HRMode mode) {
+        host_reservation_mode_ = mode;
+    }
+
     /// @brief Returns pointer to the option data configuration for this subnet.
     CfgOptionPtr getCfgOption() {
         return (cfg_option_);
@@ -89,6 +263,37 @@ protected:
     /// @brief Holds interface name for which this network is selected.
     std::string iface_name_;
 
+    /// @brief Relay information
+    ///
+    /// See @ref RelayInfo for detailed description.
+    RelayInfo relay_;
+
+    /// @brief Optional definition of a client class
+    ///
+    /// If defined, only clients belonging to that class will be allowed to use
+    /// this particular network. The default value for this is an empty list,
+    /// which means that any client is allowed, regardless of its class.
+    ///
+    /// @todo This is just a single list of allowed classes. We'll also need
+    /// to add a black-list (only classes on the list are rejected, the rest
+    /// are allowed). Implementing this will require more fancy parser logic,
+    /// so it may be a while until we support this.
+    ClientClasses white_list_;
+
+    /// @brief a Triplet (min/default/max) holding allowed renew timer values
+    Triplet<uint32_t> t1_;
+
+    /// @brief a Triplet (min/default/max) holding allowed rebind timer values
+    Triplet<uint32_t> t2_;
+
+    /// @brief a Triplet (min/default/max) holding allowed valid lifetime values
+    Triplet<uint32_t> valid_;
+
+    /// @brief Specifies host reservation mode
+    ///
+    /// See @ref HRMode type for details.
+    HRMode host_reservation_mode_;
+
     /// @brief Pointer to the option data configuration for this subnet.
     CfgOptionPtr cfg_option_;
 };

+ 8 - 58
src/lib/dhcpsrv/subnet.cc

@@ -57,11 +57,16 @@ Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
                const SubnetID id)
     : Network(), id_(id == 0 ? generateNextID() : id), prefix_(prefix),
       prefix_len_(len),
-      t1_(t1), t2_(t2), valid_(valid_lifetime),
       last_allocated_ia_(lastAddrInPrefix(prefix, len)),
       last_allocated_ta_(lastAddrInPrefix(prefix, len)),
-      last_allocated_pd_(lastAddrInPrefix(prefix, len)), relay_(relay),
-      host_reservation_mode_(HR_ALL) {
+      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,
@@ -81,33 +86,6 @@ Subnet::inRange(const isc::asiolink::IOAddress& addr) const {
     return ((first <= addr) && (addr <= last));
 }
 
-void
-Subnet::setRelayInfo(const isc::dhcp::Subnet::RelayInfo& relay) {
-    relay_ = relay;
-}
-
-bool
-Subnet::clientSupported(const isc::dhcp::ClientClasses& classes) const {
-    if (white_list_.empty()) {
-        return (true); // There is no class defined for this subnet, so we do
-                       // support everyone.
-    }
-
-    for (ClientClasses::const_iterator it = white_list_.begin();
-         it != white_list_.end(); ++it) {
-        if (classes.contains(*it)) {
-            return (true);
-        }
-    }
-
-    return (false);
-}
-
-void
-Subnet::allowClientClass(const isc::dhcp::ClientClass& class_name) {
-    white_list_.insert(class_name);
-}
-
 isc::asiolink::IOAddress Subnet::getLastAllocated(Lease::Type type) const {
     // check if the type is valid (and throw if it isn't)
     checkType(type);
@@ -471,28 +449,9 @@ Subnet::toElement() const {
     SubnetID id = getID();
     map->set("id", Element::create(static_cast<long long>(id)));
 
-    // Set relay info
-    const Subnet::RelayInfo& relay_info = getRelayInfo();
-    ElementPtr relay = Element::createMap();
-    relay->set("ip-address", Element::create(relay_info.addr_.toText()));
-    map->set("relay", relay);
-
     // Set subnet
     map->set("subnet", Element::create(toText()));
 
-    // Set renew-timer
-    map->set("renew-timer",
-             Element::create(static_cast<long long>
-                                 (getT1().get())));
-    // Set rebind-timer
-    map->set("rebind-timer",
-             Element::create(static_cast<long long>
-                                 (getT2().get())));
-    // Set valid-lifetime
-    map->set("valid-lifetime",
-             Element::create(static_cast<long long>
-                                 (getValid().get())));
-
     // Set reservation mode
     Subnet::HRMode hrmode = getHostReservationMode();
     std::string mode;
@@ -512,15 +471,6 @@ Subnet::toElement() const {
     }
     map->set("reservation-mode", Element::create(mode));
 
-    // Set client-class
-    const ClientClasses& cclasses = getClientClasses();
-    if (cclasses.size() > 1) {
-        isc_throw(ToElementError, "client-class has too many items: "
-                  << cclasses.size());
-    } else if (!cclasses.empty()) {
-        map->set("client-class", Element::create(*cclasses.cbegin()));
-    }
-
     return (map);
 }
 

+ 0 - 182
src/lib/dhcpsrv/subnet.h

@@ -10,7 +10,6 @@
 #include <asiolink/io_address.h>
 #include <cc/data.h>
 #include <dhcp/option.h>
-#include <dhcp/classify.h>
 #include <dhcp/option_space_container.h>
 #include <dhcpsrv/assignable_network.h>
 #include <dhcpsrv/lease.h>
@@ -37,47 +36,6 @@ class Subnet : public Network {
 
 public:
 
-    /// @brief Holds optional information about relay.
-    ///
-    /// In some cases it is beneficial to have additional information about
-    /// a relay configured in the subnet. For now, the structure holds only
-    /// IP address, but there may potentially be additional parameters added
-    /// later, e.g. relay interface-id or relay-id.
-    struct RelayInfo {
-
-        /// @brief default and the only constructor
-        ///
-        /// @param addr an IP address of the relay (may be :: or 0.0.0.0)
-        RelayInfo(const isc::asiolink::IOAddress& addr);
-
-        /// @brief IP address of the relay
-        isc::asiolink::IOAddress addr_;
-    };
-
-    /// @brief Specifies allowed host reservation mode.
-    ///
-    typedef enum  {
-
-        /// None - host reservation is disabled. No reservation types
-        /// are allowed.
-        HR_DISABLED,
-
-        /// Only out-of-pool reservations is allowed. This mode
-        /// allows AllocEngine to skip reservation checks when
-        /// dealing with with addresses that are in pool.
-        HR_OUT_OF_POOL,
-
-        /// Both out-of-pool and in-pool reservations are allowed. This is the
-        /// most flexible mode, where sysadmin have biggest liberty. However,
-        /// there is a non-trivial performance penalty for it, as the
-        /// AllocEngine code has to check whether there are reservations, even
-        /// when dealing with reservations from within the dynamic pools.
-        HR_ALL
-    } HRMode;
-
-    /// Pointer to the RelayInfo structure
-    typedef boost::shared_ptr<Subnet::RelayInfo> RelayInfoPtr;
-
     /// @brief checks if specified address is in range
     bool inRange(const isc::asiolink::IOAddress& addr) const;
 
@@ -97,21 +55,6 @@ public:
     /// @return true if the address is in any of the pools
     bool inPool(Lease::Type type, const isc::asiolink::IOAddress& addr) const;
 
-    /// @brief Return valid-lifetime for addresses in that prefix
-    Triplet<uint32_t> getValid() const {
-        return (valid_);
-    }
-
-    /// @brief Returns T1 (renew timer), expressed in seconds
-    Triplet<uint32_t> getT1() const {
-        return (t1_);
-    }
-
-    /// @brief Returns T2 (rebind timer), expressed in seconds
-    Triplet<uint32_t> getT2() const {
-        return (t2_);
-    }
-
     /// @brief returns the last address that was tried from this pool
     ///
     /// This method returns the last address that was attempted to be allocated
@@ -242,97 +185,6 @@ public:
         static_id_ = 1;
     }
 
-    /// @brief Sets information about relay
-    ///
-    /// In some situations where there are shared subnets (i.e. two different
-    /// subnets are available on the same physical link), there is only one
-    /// relay that handles incoming requests from clients. In such a case,
-    /// the usual subnet selection criteria based on relay belonging to the
-    /// subnet being selected are no longer sufficient and we need to explicitly
-    /// specify a relay. One notable example of such uncommon, but valid
-    /// scenario is a cable network, where there is only one CMTS (one relay),
-    /// but there are 2 distinct subnets behind it: one for cable modems
-    /// and another one for CPEs and other user equipment behind modems.
-    /// From manageability perspective, it is essential that modems get addresses
-    /// from different subnet, so users won't tinker with their modems.
-    ///
-    /// Setting this parameter is not needed in most deployments.
-    /// This structure holds IP address only for now, but it is expected to
-    /// be extended in the future.
-    ///
-    /// @param relay structure that contains relay information
-    void setRelayInfo(const isc::dhcp::Subnet::RelayInfo& relay);
-
-
-    /// @brief Returns const reference to relay information
-    ///
-    /// @note The returned reference is only valid as long as the object
-    /// returned it is valid.
-    ///
-    /// @return const reference to the relay information
-    const isc::dhcp::Subnet::RelayInfo& getRelayInfo() const {
-        return (relay_);
-    }
-
-    /// @brief checks whether this subnet supports client that belongs to
-    ///        specified classes.
-    ///
-    /// This method checks whether a client that belongs to given classes can
-    /// use this subnet. For example, if this class is reserved for client
-    /// class "foo" and the client belongs to classes "foo", "bar" and "baz",
-    /// it is supported. On the other hand, client belonging to classes
-    /// "foobar" and "zyxxy" is not supported.
-    ///
-    /// @todo: Currently the logic is simple: client is supported if it belongs
-    /// to any class mentioned in white_list_. We will eventually need a
-    /// way to specify more fancy logic (e.g. to meet all classes, not just
-    /// any)
-    ///
-    /// @param client_classes list of all classes the client belongs to
-    /// @return true if client can be supported, false otherwise
-    bool
-    clientSupported(const isc::dhcp::ClientClasses& client_classes) const;
-
-    /// @brief adds class class_name to the list of supported classes
-    ///
-    /// Also see explanation note in @ref white_list_.
-    ///
-    /// @param class_name client class to be supported by this subnet
-    void
-    allowClientClass(const isc::dhcp::ClientClass& class_name);
-
-    /// @brief returns the client class white list
-    ///
-    /// @note The returned reference is only valid as long as the object
-    /// returned it is valid.
-    ///
-    /// @return client classes @ref white_list_
-    const isc::dhcp::ClientClasses& getClientClasses() const {
-        return (white_list_);
-    }
-
-    /// @brief Specifies what type of Host Reservations are supported.
-    ///
-    /// Host reservations may be either in-pool (they reserve an address that
-    /// is in the dynamic pool) or out-of-pool (they reserve an address that is
-    /// not in the dynamic pool). HR may also be completely disabled for
-    /// performance reasons.
-    ///
-    /// @return whether in-pool host reservations are allowed.
-    HRMode
-    getHostReservationMode() const {
-        return (host_reservation_mode_);
-    }
-
-    /// @brief Sets host reservation mode.
-    ///
-    /// See @ref getHostReservationMode for details.
-    ///
-    /// @param mode mode to be set
-    void setHostReservationMode(HRMode mode) {
-        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
@@ -480,15 +332,6 @@ protected:
     /// @brief a prefix length of the subnet
     uint8_t prefix_len_;
 
-    /// @brief a triplet (min/default/max) holding allowed renew timer values
-    Triplet<uint32_t> t1_;
-
-    /// @brief a triplet (min/default/max) holding allowed rebind timer values
-    Triplet<uint32_t> t2_;
-
-    /// @brief a triplet (min/default/max) holding allowed valid lifetime values
-    Triplet<uint32_t> valid_;
-
     /// @brief last allocated address
     ///
     /// This is the last allocated address that was previously allocated from
@@ -513,31 +356,6 @@ protected:
     /// @brief Name of the network interface (if connected directly)
     std::string iface_;
 
-    /// @brief Relay information
-    ///
-    /// See @ref RelayInfo for detailed description. This structure is public,
-    /// so its fields are easily accessible. Making it protected would bring in
-    /// the issue of returning references that may become stale after its parent
-    /// subnet object disappears.
-    RelayInfo relay_;
-
-    /// @brief optional definition of a client class
-    ///
-    /// If defined, only clients belonging to that class will be allowed to use
-    /// this particular subnet. The default value for this is an empty list,
-    /// which means that any client is allowed, regardless of its class.
-    ///
-    /// @todo This is just a single list of allowed classes. We'll also need
-    /// to add a black-list (only classes on the list are rejected, the rest
-    /// are allowed). Implementing this will require more fancy parser logic,
-    /// so it may be a while until we support this.
-    ClientClasses white_list_;
-
-    /// @brief Specifies host reservation mode
-    ///
-    /// See @ref HRMode type for details.
-    HRMode host_reservation_mode_;
-
     /// @brief Pointer to a shared network that subnet belongs to.
     WeakNetworkPtr shared_network_;
 };