2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 05:27:55 +00:00

[5425] Added basic support (alloc engine todo)

This commit is contained in:
Francis Dupont 2017-11-20 00:27:46 +01:00
parent c25dce8b6b
commit 3f877a825a
12 changed files with 172 additions and 6 deletions

View File

@ -137,6 +137,27 @@
"relay": { "relay": {
"ip-address": "192.168.1.1" "ip-address": "192.168.1.1"
} }
},
{
// This subnet is divided in two pools for unknown and
// known (i.e. which have a reservation) clients.
"pools": [
{
"pool": "192.0.8.100 - 192.0.8.200",
"known-clients": "never"
},
{
"pool": "192.0.9.100 - 192.0.9.200",
"known-clients": "only"
}
],
"subnet": "192.0.8.0/23",
"reservations": [
{ "hw-address": "00:00:00:11:22:33" },
{ "hw-address": "00:00:00:44:55:66" },
{ "hw-address": "00:00:00:77:88:99" },
{ "hw-address": "00:00:00:aa:bb:cc" }
]
} }
] ]
}, },

View File

@ -133,7 +133,28 @@
// and another is when there is a shared subnet scenario. // and another is when there is a shared subnet scenario.
"relay": { "relay": {
"ip-address": "3000::1" "ip-address": "3000::1"
} },
},
{
// This subnet is divided in two pools for unknown and
// known (i.e. which have a reservation) clients.
"pools": [
{
"pool": "2001:db8:8::/64",
"known-clients": "never"
},
{
"pool": "2001:db8:9::/64",
"known-clients": "only"
}
],
"subnet": "2001:db8:8::/46",
"reservations": [
{ "hw-address": "00:00:00:11:22:33" },
{ "hw-address": "00:00:00:44:55:66" },
{ "hw-address": "00:00:00:77:88:99" },
{ "hw-address": "00:00:00:aa:bb:cc" }
]
} }
] ]
}, },

View File

@ -2090,6 +2090,15 @@ It is merely echoed by the server
at the pool level, see <xref linkend="classification-pools"/>. at the pool level, see <xref linkend="classification-pools"/>.
</para> </para>
<para>
In a similar way a pool can be constrained to serve only known clients,
i.e. clients which have a reservation, using
<command>"known-clients": "only"</command>, or only unknown clients
with <command>"known-clients": "never"</command>. One can assign
addresses to registered clients without giving a different address per
reservations, for instance when there is not enough available addresses.
</para>
<para> <para>
The process of doing classification is conducted in three steps. The first step The process of doing classification is conducted in three steps. The first step
is to assess an incoming packet and assign it to zero or more classes. The is to assess an incoming packet and assign it to zero or more classes. The

View File

@ -1950,6 +1950,15 @@ should include options from the isc option space:
linkend="classification-pools"/>. linkend="classification-pools"/>.
</para> </para>
<para>
In a similar way a pool can be constrained to serve only known clients,
i.e. clients which have a reservation, using
<command>"known-clients": "only"</command>, or only unknown clients
with <command>"known-clients": "never"</command>. One can assign
prefixes to registered clients without giving a different prefix per
reservations, forinstance when there is not enough available prefixes.
</para>
<para> <para>
The process of doing classification is conducted in three steps. The first step The process of doing classification is conducted in three steps. The first step
is to assess an incoming packet and assign it to zero or more classes. The is to assess an incoming packet and assign it to zero or more classes. The

View File

@ -387,6 +387,19 @@ PoolParser::parse(PoolStoragePtr pools,
pool->allowClientClass(cclass); pool->allowClientClass(cclass);
} }
} }
// Known-clients.
ConstElementPtr known_clients = pool_structure->get("known-clients");
if (known_clients) {
string kc = known_clients->stringValue();
if (kc == "only") {
pool->setKnownClients(Pool::SERVE_KNOWN);
} else if (kc == "never") {
pool->setKnownClients(Pool::SERVE_UNKNOWN);
} else
isc_throw(DhcpConfigError, "invalid known-clients value: " << kc
<< " (" << known_clients->getPosition() << ")");
}
} }
//****************************** Pool4Parser ************************* //****************************** Pool4Parser *************************
@ -861,6 +874,11 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
client_class_ = client_class; client_class_ = client_class;
} }
ConstElementPtr known_clients = pd_pool_->get("known-clients");
if (known_clients) {
known_clients_ = known_clients;
}
// Check the pool parameters. It will throw an exception if any // Check the pool parameters. It will throw an exception if any
// of the required parameters are invalid. // of the required parameters are invalid.
try { try {
@ -884,7 +902,6 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
pool_->setContext(user_context_); pool_->setContext(user_context_);
} }
if (client_class_) { if (client_class_) {
string cclass = client_class_->stringValue(); string cclass = client_class_->stringValue();
if (!cclass.empty()) { if (!cclass.empty()) {
@ -892,6 +909,18 @@ PdPoolParser::parse(PoolStoragePtr pools, ConstElementPtr pd_pool_) {
} }
} }
if (known_clients_) {
string kc = known_clients_->stringValue();
if (kc == "only") {
pool_->setKnownClients(Pool::SERVE_KNOWN);
} else if (kc == "never") {
pool_->setKnownClients(Pool::SERVE_UNKNOWN);
} else
isc_throw(isc::dhcp::DhcpConfigError,
"invalid known-clients value: " << kc
<< " (" << known_clients_->getPosition() << ")");
}
// Add the local pool to the external storage ptr. // Add the local pool to the external storage ptr.
pools->push_back(pool_); pools->push_back(pool_);
} }

View File

@ -655,6 +655,7 @@ private:
isc::data::ConstElementPtr client_class_; isc::data::ConstElementPtr client_class_;
isc::data::ConstElementPtr known_clients_;
}; };
/// @brief Parser for a list of prefix delegation pools. /// @brief Parser for a list of prefix delegation pools.

View File

@ -19,6 +19,7 @@ Pool::Pool(Lease::Type type, const isc::asiolink::IOAddress& first,
const isc::asiolink::IOAddress& last) const isc::asiolink::IOAddress& last)
:id_(getNextID()), first_(first), last_(last), type_(type), :id_(getNextID()), first_(first), last_(last), type_(type),
capacity_(0), cfg_option_(new CfgOption()), white_list_(), capacity_(0), cfg_option_(new CfgOption()), white_list_(),
known_clients_(SERVE_BOTH),
last_allocated_(first), last_allocated_valid_(false) { last_allocated_(first), last_allocated_valid_(false) {
} }
@ -121,6 +122,13 @@ Pool::toElement() const {
map->set("client-class", Element::create(*cclasses.cbegin())); map->set("client-class", Element::create(*cclasses.cbegin()));
} }
// Set known-clients
KnownClients kc = getKnownClients();
if (kc != SERVE_BOTH) {
map->set("known-clients",
Element::create(kc == SERVE_KNOWN ? "only" : "never"));
}
return (map); return (map);
} }

View File

@ -28,6 +28,13 @@ namespace dhcp {
class Pool { class Pool {
public: public:
/// @brief Value of known clients
typedef enum {
SERVE_BOTH = 0, ///< the pool serves both known and unknown clients
SERVE_KNOWN = 1, ///< the pool serves only known clients
SERVE_UNKNOWN = 2 ///< the pool never serves known clients
} KnownClients;
/// @note: /// @note:
/// PoolType enum was removed. Please use Lease::Type instead /// PoolType enum was removed. Please use Lease::Type instead
@ -133,6 +140,16 @@ public:
return (white_list_); return (white_list_);
} }
/// @brief Returns the value of known clients
KnownClients getKnownClients() const {
return (known_clients_);
}
/// @brief Sets the value of known clients
void setKnownClients(KnownClients known_clients) {
known_clients_ = known_clients;
}
/// @brief returns the last address that was tried from this pool /// @brief returns the last address that was tried from this pool
/// ///
/// @return address/prefix that was last tried from this pool /// @return address/prefix that was last tried from this pool
@ -222,6 +239,9 @@ protected:
/// @ref Network::white_list_ /// @ref Network::white_list_
ClientClasses white_list_; ClientClasses white_list_;
/// @brief Value of known clients
KnownClients known_clients_;
/// @brief Pointer to the user context (may be NULL) /// @brief Pointer to the user context (may be NULL)
data::ConstElementPtr user_context_; data::ConstElementPtr user_context_;

View File

@ -742,6 +742,13 @@ Subnet6::toElement() const {
} else if (!cclasses.empty()) { } else if (!cclasses.empty()) {
pool_map->set("client-class", Element::create(*cclasses.cbegin())); pool_map->set("client-class", Element::create(*cclasses.cbegin()));
} }
// Set known-clients
Pool::KnownClients kc = (*pool)->getKnownClients();
if (kc != Pool::SERVE_BOTH) {
pool_map->set("known-clients",
Element::create(kc == Pool::SERVE_KNOWN ?
"only" : "never"));
}
// Push on the pool list // Push on the pool list
pool_list->add(pool_map); pool_list->add(pool_map);
} }
@ -804,6 +811,13 @@ Subnet6::toElement() const {
} else if (!cclasses.empty()) { } else if (!cclasses.empty()) {
pool_map->set("client-class", Element::create(*cclasses.cbegin())); pool_map->set("client-class", Element::create(*cclasses.cbegin()));
} }
// Set known-clients
Pool::KnownClients kc = pdpool->getKnownClients();
if (kc != Pool::SERVE_BOTH) {
pool_map->set("known-clients",
Element::create(kc == Pool::SERVE_KNOWN ?
"only" : "never"));
}
// Push on the pool list // Push on the pool list
pdpool_list->add(pool_map); pdpool_list->add(pool_map);
} }

View File

@ -813,6 +813,7 @@ TEST(CfgSubnets4Test, unparsePool) {
Pool4Ptr pool1(new Pool4(IOAddress("192.0.2.1"), IOAddress("192.0.2.10"))); Pool4Ptr pool1(new Pool4(IOAddress("192.0.2.1"), IOAddress("192.0.2.10")));
Pool4Ptr pool2(new Pool4(IOAddress("192.0.2.64"), 26)); Pool4Ptr pool2(new Pool4(IOAddress("192.0.2.64"), 26));
pool2->allowClientClass("bar"); pool2->allowClientClass("bar");
pool2->setKnownClients(Pool::SERVE_KNOWN);
subnet->addPool(pool1); subnet->addPool(pool1);
subnet->addPool(pool2); subnet->addPool(pool2);
@ -843,7 +844,8 @@ TEST(CfgSubnets4Test, unparsePool) {
" },{\n" " },{\n"
" \"option-data\": [ ],\n" " \"option-data\": [ ],\n"
" \"pool\": \"192.0.2.64/26\",\n" " \"pool\": \"192.0.2.64/26\",\n"
" \"client-class\": \"bar\"\n" " \"client-class\": \"bar\",\n"
" \"known-clients\": \"only\"\n"
" }\n" " }\n"
" ]\n" " ]\n"
"} ]\n"; "} ]\n";

View File

@ -504,6 +504,7 @@ TEST(CfgSubnets6Test, unparsePool) {
IOAddress("2001:db8:1::199"))); IOAddress("2001:db8:1::199")));
Pool6Ptr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64)); Pool6Ptr pool2(new Pool6(Lease::TYPE_NA, IOAddress("2001:db8:1:1::"), 64));
pool2->allowClientClass("bar"); pool2->allowClientClass("bar");
pool2->setKnownClients(Pool::SERVE_UNKNOWN);
subnet->addPool(pool1); subnet->addPool(pool1);
subnet->addPool(pool2); subnet->addPool(pool2);
@ -528,7 +529,8 @@ TEST(CfgSubnets6Test, unparsePool) {
" },{\n" " },{\n"
" \"pool\": \"2001:db8:1:1::/64\",\n" " \"pool\": \"2001:db8:1:1::/64\",\n"
" \"option-data\": [ ],\n" " \"option-data\": [ ],\n"
" \"client-class\": \"bar\"\n" " \"client-class\": \"bar\",\n"
" \"known-clients\": \"never\"\n"
" }\n" " }\n"
" ],\n" " ],\n"
" \"pd-pools\": [ ],\n" " \"pd-pools\": [ ],\n"
@ -550,6 +552,7 @@ TEST(CfgSubnets6Test, unparsePdPool) {
Pool6Ptr pdpool2(new Pool6(IOAddress("2001:db8:3::"), 48, 56, Pool6Ptr pdpool2(new Pool6(IOAddress("2001:db8:3::"), 48, 56,
IOAddress("2001:db8:3::"), 64)); IOAddress("2001:db8:3::"), 64));
pdpool2->allowClientClass("bar"); pdpool2->allowClientClass("bar");
pdpool2->setKnownClients(Pool::SERVE_KNOWN);
subnet->addPool(pdpool1); subnet->addPool(pdpool1);
subnet->addPool(pdpool2); subnet->addPool(pdpool2);
@ -581,7 +584,8 @@ TEST(CfgSubnets6Test, unparsePdPool) {
" \"excluded-prefix\": \"2001:db8:3::\",\n" " \"excluded-prefix\": \"2001:db8:3::\",\n"
" \"excluded-prefix-len\": 64,\n" " \"excluded-prefix-len\": 64,\n"
" \"option-data\": [ ],\n" " \"option-data\": [ ],\n"
" \"client-class\": \"bar\"\n" " \"client-class\": \"bar\",\n"
" \"known-clients\": \"only\"\n"
" }\n" " }\n"
" ],\n" " ],\n"
" \"option-data\": [ ]\n" " \"option-data\": [ ]\n"

View File

@ -268,6 +268,20 @@ TEST(Pool4Test, clientClasses) {
EXPECT_TRUE(pool->clientSupported(bar_class)); EXPECT_TRUE(pool->clientSupported(bar_class));
} }
// This test checks that handling for known-clients is valid.
TEST(Pool4Test, knownClients) {
// Create a pool.
Pool4Ptr pool(new Pool4(IOAddress("192.0.2.0"),
IOAddress("192.0.2.255")));
// This pool serves everybody by default.
EXPECT_EQ(Pool::SERVE_BOTH, pool->getKnownClients());
// Set it to only known clients.
pool->setKnownClients(Pool::SERVE_KNOWN);
EXPECT_EQ(Pool::SERVE_KNOWN,pool->getKnownClients());
}
// This test checks that handling for last allocated address/prefix is valid. // This test checks that handling for last allocated address/prefix is valid.
TEST(Pool4Test, lastAllocated) { TEST(Pool4Test, lastAllocated) {
// Create a pool. // Create a pool.
@ -638,7 +652,7 @@ TEST(Pool6Test, clientClass) {
TEST(Pool6Test, clientClasses) { TEST(Pool6Test, clientClasses) {
// Create a pool. // Create a pool.
Pool6 pool(Lease::TYPE_NA, IOAddress("2001:db8::1"), Pool6 pool(Lease::TYPE_NA, IOAddress("2001:db8::1"),
IOAddress("2001:db8::2")); IOAddress("2001:db8::2"));
// This client does not belong to any class. // This client does not belong to any class.
isc::dhcp::ClientClasses no_class; isc::dhcp::ClientClasses no_class;
@ -672,6 +686,20 @@ TEST(Pool6Test, clientClasses) {
EXPECT_TRUE(pool.clientSupported(bar_class)); EXPECT_TRUE(pool.clientSupported(bar_class));
} }
// This test checks that handling for known-clients is valid.
TEST(Pool6Test, knownClients) {
// Create a pool.
Pool6 pool(Lease::TYPE_NA, IOAddress("2001:db8::1"),
IOAddress("2001:db8::2"));
// This pool serves everybody by default.
EXPECT_EQ(Pool::SERVE_BOTH, pool.getKnownClients());
// Set it to only known clients.
pool.setKnownClients(Pool::SERVE_KNOWN);
EXPECT_EQ(Pool::SERVE_KNOWN,pool.getKnownClients());
}
// This test checks that handling for last allocated address/prefix is valid. // This test checks that handling for last allocated address/prefix is valid.
TEST(Pool6Test, lastAllocated) { TEST(Pool6Test, lastAllocated) {
// Create a pool. // Create a pool.