summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcpsrv
diff options
context:
space:
mode:
authorFrancis Dupont <fdupont@isc.org>2018-02-23 16:45:46 +0100
committerFrancis Dupont <fdupont@isc.org>2018-02-23 16:45:46 +0100
commitd2bad4f7e32491c36d741642a2bb0baa040a7e67 (patch)
tree6ae98efd7409d907deca2933cad1f74511ea84f4 /src/lib/dhcpsrv
parent[5533] Introduce get[46]Any and add tests (diff)
downloadkea-d2bad4f7e32491c36d741642a2bb0baa040a7e67.tar.xz
kea-d2bad4f7e32491c36d741642a2bb0baa040a7e67.zip
[5533] Checkpoint: added code, test todo (where?)
Diffstat (limited to 'src/lib/dhcpsrv')
-rw-r--r--src/lib/dhcpsrv/Makefile.am2
-rw-r--r--src/lib/dhcpsrv/cache_host_data_source.h64
-rw-r--r--src/lib/dhcpsrv/cfg_db_access.cc3
-rw-r--r--src/lib/dhcpsrv/host_mgr.cc77
-rw-r--r--src/lib/dhcpsrv/host_mgr.h110
5 files changed, 217 insertions, 39 deletions
diff --git a/src/lib/dhcpsrv/Makefile.am b/src/lib/dhcpsrv/Makefile.am
index a9c5ea7c36..34fd3a88e6 100644
--- a/src/lib/dhcpsrv/Makefile.am
+++ b/src/lib/dhcpsrv/Makefile.am
@@ -89,6 +89,7 @@ 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 += cache_host_data_source.h
libkea_dhcpsrv_la_SOURCES += callout_handle_store.h
libkea_dhcpsrv_la_SOURCES += cfg_4o6.cc cfg_4o6.h
libkea_dhcpsrv_la_SOURCES += cfg_db_access.cc cfg_db_access.h
@@ -246,6 +247,7 @@ libkea_dhcpsrv_include_HEADERS = \
alloc_engine_log.h \
assignable_network.h \
base_host_data_source.h \
+ cache_host_data_source.h \
callout_handle_store.h \
cfg_4o6.h \
cfg_db_access.h \
diff --git a/src/lib/dhcpsrv/cache_host_data_source.h b/src/lib/dhcpsrv/cache_host_data_source.h
new file mode 100644
index 0000000000..d6d84bc38a
--- /dev/null
+++ b/src/lib/dhcpsrv/cache_host_data_source.h
@@ -0,0 +1,64 @@
+// Copyright (C) 2018 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the End User License
+// Agreement. See COPYING file in the premium/ directory.
+
+#ifndef CACHE_HOST_DATA_SOURCE_H
+#define CACHE_HOST_DATA_SOURCE_H
+
+#include <dhcpsrv/base_host_data_source.h>
+
+namespace isc {
+namespace dhcp {
+
+/// @brief Abstract interface extending base simple data source for host
+/// reservations to host cache.
+/// Only the insert() method is required to use the cache.
+class CacheHostDataSource : public BaseHostDataSource {
+public:
+
+ /// @brief Default destructor implementation.
+ virtual ~CacheHostDataSource() { }
+
+ /// @brief Insert a host into the cache.
+ ///
+ /// Does the same than @c add() but with a different purpose.
+ ///
+ /// @param host Pointer to the new @c Host object being inserted.
+ /// @param[in,out] overwrite -1 if accepting conflicts, 0 if removing
+ /// conflicting entries, set to the number of removed entries.
+ /// @return true when succeeded.
+ virtual bool insert(const ConstHostPtr& host, int& overwrite) = 0;
+
+ /// @brief Remove a host from the cache.
+ ///
+ /// Does the same than @c del, @c del4 or @c del6 but with
+ /// a more uniform interface and a different purpose.
+ ///
+ /// @param host Pointer to the existing @c Host object being removed.
+ /// @return true when found and removed.
+ virtual bool remove(const HostPtr& host) = 0;
+
+ /// @brief Flush entries.
+ ///
+ /// @param count number of entries to remove, 0 means all.
+ virtual void flush(size_t count) = 0;
+
+ /// @brief Return the number of entries.
+ ///
+ /// @return the current number of active entries in the cache.
+ virtual size_t size() const = 0;
+
+ /// @brief Return the maximum number of entries.
+ ///
+ /// @return the maximum number of entries, 0 means unbound.
+ virtual size_t capacity() const = 0;
+};
+
+/// @brief CacheHostDataSource pointer.
+typedef boost::shared_ptr<CacheHostDataSource> CacheHostDataSourcePtr;
+
+} // end of namespace isc::dhcp
+} // end of namespace isc
+
+#endif // CACHE_HOST_DATA_SOURCE_H
diff --git a/src/lib/dhcpsrv/cfg_db_access.cc b/src/lib/dhcpsrv/cfg_db_access.cc
index ad6c396587..2163f1ec96 100644
--- a/src/lib/dhcpsrv/cfg_db_access.cc
+++ b/src/lib/dhcpsrv/cfg_db_access.cc
@@ -60,6 +60,9 @@ CfgDbAccess::createManagers() const {
it != host_db_access_list.end(); ++it) {
HostMgr::addSource(*it);
}
+
+ // Check for a host cache.
+ HostMgr::checkCacheSource();
}
std::string
diff --git a/src/lib/dhcpsrv/host_mgr.cc b/src/lib/dhcpsrv/host_mgr.cc
index 1cb45c2ddb..c776d90444 100644
--- a/src/lib/dhcpsrv/host_mgr.cc
+++ b/src/lib/dhcpsrv/host_mgr.cc
@@ -64,6 +64,24 @@ HostMgr::getHostDataSource() const {
return (alternate_sources_[0]);
}
+bool
+HostMgr::checkCacheSource() {
+ if (getHostMgrPtr()->cache_ptr_) {
+ return (true);
+ }
+ HostDataSourceList& sources = getHostMgrPtr()->alternate_sources_;
+ if (sources.empty()) {
+ return (false);
+ }
+ CacheHostDataSourcePtr cache_ptr =
+ boost::dynamic_pointer_cast<CacheHostDataSource>(sources[0]);
+ if (cache_ptr) {
+ getHostMgrPtr()->cache_ptr_ = cache_ptr;
+ return (true);
+ }
+ return (false);
+}
+
HostMgr&
HostMgr::instance() {
boost::scoped_ptr<HostMgr>& host_mgr_ptr = getHostMgrPtr();
@@ -132,6 +150,9 @@ HostMgr::get4(const SubnetID& subnet_id, const HWAddrPtr& hwaddr,
if (!host && hwaddr) {
host = (*it)->get4(subnet_id, hwaddr, DuidPtr());
}
+ if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
+ cache(host);
+ }
}
if (host && host->getNegative()) {
return (ConstHostPtr());
@@ -171,6 +192,9 @@ HostMgr::get4Any(const SubnetID& subnet_id,
.arg((*it)->getType())
.arg(host->toText());
+ if (cache_ptr_ && (it != alternate_sources_.begin())) {
+ cache(host);
+ }
return (host);
}
}
@@ -179,6 +203,10 @@ HostMgr::get4Any(const SubnetID& subnet_id,
.arg(subnet_id)
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
identifier_len));
+ if (negative_caching_) {
+ cacheNegative(subnet_id, SubnetID(0),
+ identifier_type, identifier_begin, identifier_len);
+ }
return (host);
}
@@ -209,6 +237,9 @@ HostMgr::get4(const SubnetID& subnet_id,
for (auto it = alternate_sources_.begin();
!host && it != alternate_sources_.end(); ++it) {
host = (*it)->get4(subnet_id, address);
+ if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
+ cache(host);
+ }
}
if (host && host->getNegative()) {
return (ConstHostPtr());
@@ -238,6 +269,9 @@ HostMgr::get6(const SubnetID& subnet_id, const DuidPtr& duid,
if (!host && hwaddr) {
host = (*it)->get6(subnet_id, DuidPtr(), hwaddr);
}
+ if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
+ cache(host);
+ }
}
if (host && host->getNegative()) {
return (ConstHostPtr());
@@ -258,6 +292,9 @@ HostMgr::get6(const IOAddress& prefix, const uint8_t prefix_len) const {
for (auto it = alternate_sources_.begin();
!host && it != alternate_sources_.end(); ++it) {
host = (*it)->get6(prefix, prefix_len);
+ if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
+ cache(host);
+ }
}
if (host && host->getNegative()) {
return (ConstHostPtr());
@@ -298,6 +335,9 @@ HostMgr::get6Any(const SubnetID& subnet_id,
.arg((*it)->getType())
.arg(host->toText());
+ if (cache_ptr_ && (it != alternate_sources_.begin())) {
+ cache(host);
+ }
return (host);
}
}
@@ -308,6 +348,11 @@ HostMgr::get6Any(const SubnetID& subnet_id,
.arg(Host::getIdentifierAsText(identifier_type, identifier_begin,
identifier_len));
+ if (negative_caching_) {
+ cacheNegative(SubnetID(0), subnet_id,
+ identifier_type, identifier_begin, identifier_len);
+ }
+
return (host);
}
@@ -338,6 +383,9 @@ HostMgr::get6(const SubnetID& subnet_id,
for (auto it = alternate_sources_.begin();
!host && it != alternate_sources_.end(); ++it) {
host = (*it)->get6(subnet_id, addr);
+ if (host && cache_ptr_ && (it != alternate_sources_.begin())) {
+ cache(host);
+ }
}
if (host && host->getNegative()) {
return (ConstHostPtr());
@@ -413,5 +461,34 @@ HostMgr::del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_
return (false);
}
+void
+HostMgr::cache(ConstHostPtr host) const {
+ if (cache_ptr_) {
+ // Replace any existing value.
+ int overwrite = 0;
+ // Don't check the result as it does not matter?
+ cache_ptr_->insert(host, overwrite);
+ }
+}
+
+void
+HostMgr::cacheNegative(const SubnetID& ipv4_subnet_id,
+ const SubnetID& ipv6_subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin,
+ const size_t identifier_len) const {
+ if (cache_ptr_ && negative_caching_) {
+ HostPtr host(new Host(identifier_begin, identifier_len,
+ identifier_type,
+ ipv4_subnet_id, ipv6_subnet_id,
+ IOAddress::IPV4_ZERO_ADDRESS()));
+ host->setNegative(true);
+ // Don't replace any existing value.
+ int overwrite = -1;
+ // nor matter if it fails.
+ cache_ptr_->insert(host, overwrite);
+ }
+}
+
} // end of isc::dhcp namespace
} // end of isc namespace
diff --git a/src/lib/dhcpsrv/host_mgr.h b/src/lib/dhcpsrv/host_mgr.h
index fa003ac22d..e7392172cf 100644
--- a/src/lib/dhcpsrv/host_mgr.h
+++ b/src/lib/dhcpsrv/host_mgr.h
@@ -10,6 +10,7 @@
#include <dhcp/duid.h>
#include <dhcp/hwaddr.h>
#include <dhcpsrv/base_host_data_source.h>
+#include <dhcpsrv/cache_host_data_source.h>
#include <dhcpsrv/host.h>
#include <dhcpsrv/subnet_id.h>
#include <boost/noncopyable.hpp>
@@ -81,6 +82,12 @@ public:
/// @brief Delete all alternate host data source.
static void delAllSources();
+ /// @brief Check for the cache host data source.
+ ///
+ /// Checks if the first host data source implements
+ /// the cache abstract class and sets cache_ptr_.
+ static bool checkCacheSource();
+
/// @brief Returns a sole instance of the @c HostMgr.
///
/// This method should be used to retrieve an instance of the @c HostMgr
@@ -308,44 +315,6 @@ public:
/// @return true if addition was successful.
virtual bool add(const HostPtr& host);
- /// @brief Return backend type
- ///
- /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
- ///
- /// @return Type of the backend.
- virtual std::string getType() const {
- return (std::string("host_mgr"));
- }
-
- /// @brief Returns the host data source list.
- ///
- /// @return reference to the host data source list.
- HostDataSourceList& getHostDataSourceList() {
- return (alternate_sources_);
- }
-
- /// @brief Returns the fist host data source.
- ///
- /// May return NULL if the host data source list is empty.
- /// @return pointer to the first host data source (or NULL)
- HostDataSourcePtr getHostDataSource() const;
-
- /// @brief Sets alternate host data source list.
- ///
- /// Note: This should be used only for testing. Do not use
- /// in production. Normal control flow assumes that
- /// HostMgr::create() and HostMgr::add() is called and it instantiates
- /// appropriate host data sources. However, some tests
- /// (e.g. host_cmds) implement their own very simple
- /// data source. It's not production ready by any means,
- /// so it does not belong in host_data_source_factory.cc.
- /// The testing nature of this method is reflected in its name.
- ///
- /// @param sources new source list to be set
- void setTestHostDataSourceList(const HostDataSourceList& sources) {
- alternate_sources_ = sources;
- }
-
/// @brief Attempts to delete a host by address.
///
/// This method supports both v4 and v6.
@@ -383,14 +352,77 @@ public:
del6(const SubnetID& subnet_id, const Host::IdentifierType& identifier_type,
const uint8_t* identifier_begin, const size_t identifier_len);
+ /// @brief Return backend type
+ ///
+ /// Returns the type of the backend (e.g. "mysql", "memfile" etc.)
+ ///
+ /// @return Type of the backend.
+ virtual std::string getType() const {
+ return (std::string("host_mgr"));
+ }
+
+ /// @brief Returns the host data source list.
+ ///
+ /// @return reference to the host data source list.
+ HostDataSourceList& getHostDataSourceList() {
+ return (alternate_sources_);
+ }
+
+ /// @brief Returns the first host data source.
+ ///
+ /// May return NULL if the host data source list is empty.
+ /// @return pointer to the first host data source (or NULL).
+ HostDataSourcePtr getHostDataSource() const;
+
+ /// @brief Returns the negative caching flag.
+ ///
+ /// @return the negative caching flag.
+ bool getNegativeCaching() const {
+ return (negative_caching_);
+ }
+
+ /// @brief Sets the negative caching flag.
+ ///
+ void setNegativeCaching(bool negative_caching) {
+ negative_caching_ = negative_caching;
+ }
+
+protected:
+ /// @brief The negative caching flag.
+ ///
+ /// When true and the first data source is a cache negative answers
+ /// to get[46] for aubnet and identifier are cached.
+ bool negative_caching_;
+
+ /// @brief Cache an answer.
+ ///
+ /// @param host Pointer to the missied host.
+ virtual void cache(ConstHostPtr host) const;
+
+ /// @brief Cache a negative answer.
+ ///
+ /// @param ipv4_subnet_id Identifier of the IPv4 subnet.
+ /// @param ipv6_subnet_id Identifier of the IPv6 subnet.
+ /// @param identifier_type Identifier type.
+ /// @param identifier_begin Pointer to a beginning of the Identifier.
+ /// @param identifier_len Identifier length.
+ virtual void cacheNegative(const SubnetID& ipv4_subnet_id,
+ const SubnetID& ipv6_subnet_id,
+ const Host::IdentifierType& identifier_type,
+ const uint8_t* identifier_begin,
+ const size_t identifier_len) const;
+
private:
/// @brief Private default constructor.
- HostMgr() { }
+ HostMgr() : negative_caching_(false) { }
/// @brief List of alternate host data sources.
HostDataSourceList alternate_sources_;
+ /// @brief Pointer to the cache.
+ CacheHostDataSourcePtr cache_ptr_;
+
/// @brief Returns a pointer to the currently used instance of the
/// @c HostMgr.
static boost::scoped_ptr<HostMgr>& getHostMgrPtr();