From: Marcin Siodelski Date: Tue, 5 Sep 2017 10:03:00 +0000 (+0200) Subject: [5305] Moved common parameters from Subnet to Network. X-Git-Tag: trac5073a_base~11^2~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c5e695d31d0c68805540b86dd91e718b3a4000b4;p=thirdparty%2Fkea.git [5305] Moved common parameters from Subnet to Network. --- diff --git a/src/lib/dhcpsrv/network.cc b/src/lib/dhcpsrv/network.cc index 0b6cb1aa65..7b1378908d 100644 --- a/src/lib/dhcpsrv/network.cc +++ b/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 + (getT1().get()))); + // Set rebind-timer + map->set("rebind-timer", + Element::create(static_cast + (getT2().get()))); + // Set valid-lifetime + map->set("valid-lifetime", + Element::create(static_cast + (getValid().get()))); + // Set options ConstCfgOptionPtr opts = getCfgOption(); map->set("option-data", opts->toElement()); diff --git a/src/lib/dhcpsrv/network.h b/src/lib/dhcpsrv/network.h index 99e03e842d..c5d9b9491d 100644 --- a/src/lib/dhcpsrv/network.h +++ b/src/lib/dhcpsrv/network.h @@ -7,12 +7,16 @@ #ifndef NETWORK_H #define NETWORK_H +#include #include #include +#include #include #include +#include #include #include +#include #include 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 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 getValid() const { + return (valid_); + } + + /// @brief Sets new valid lifetime for a network. + /// + /// @param valid New valid lifetime in seconds. + void setValid(const Triplet& valid) { + valid_ = valid; + } + + /// @brief Returns T1 (renew timer), expressed in seconds + Triplet getT1() const { + return (t1_); + } + + /// @brief Sets new renew timer for a network. + /// + /// @param t1 New renew timer value in seconds. + void setT1(const Triplet& t1) { + t1_ = t1; + } + + /// @brief Returns T2 (rebind timer), expressed in seconds + Triplet getT2() const { + return (t2_); + } + + /// @brief Sets new rebind timer for a network. + /// + /// @param t2 New rebind timer value in seconds. + void setT2(const Triplet& 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 t1_; + + /// @brief a Triplet (min/default/max) holding allowed rebind timer values + Triplet t2_; + + /// @brief a Triplet (min/default/max) holding allowed valid lifetime values + Triplet 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_; }; diff --git a/src/lib/dhcpsrv/subnet.cc b/src/lib/dhcpsrv/subnet.cc index 9434509d0c..c70bd9457b 100644 --- a/src/lib/dhcpsrv/subnet.cc +++ b/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(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 - (getT1().get()))); - // Set rebind-timer - map->set("rebind-timer", - Element::create(static_cast - (getT2().get()))); - // Set valid-lifetime - map->set("valid-lifetime", - Element::create(static_cast - (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); } diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h index 75d3fac1c3..8845ce4190 100644 --- a/src/lib/dhcpsrv/subnet.h +++ b/src/lib/dhcpsrv/subnet.h @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -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 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 getValid() const { - return (valid_); - } - - /// @brief Returns T1 (renew timer), expressed in seconds - Triplet getT1() const { - return (t1_); - } - - /// @brief Returns T2 (rebind timer), expressed in seconds - Triplet 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 t1_; - - /// @brief a triplet (min/default/max) holding allowed rebind timer values - Triplet t2_; - - /// @brief a triplet (min/default/max) holding allowed valid lifetime values - Triplet 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_; };