Commit 2de90c47 authored by Francis Dupont's avatar Francis Dupont
Browse files

[5374] Checkpoint: HA tests

parent d095150b
......@@ -64,6 +64,17 @@ namespace {
/// option[93].hex == 0x0007, set server-hostname to deneb
/// option[93].hex == 0x0006, set boot-file-name to pxelinux.0
/// option[93].hex == 0x0001, set boot-file-name to ipxe.efi
///
/// - Configuration 4:
/// - Used for complex membership (example taken from HA)
/// - 1 subnet: 10.0.0.0/24
/// - 4 pools: 10.0.0.10-10.0.0.49, 10.0.0.60-10.0.0.99,
/// 10.0.0.110-10.0.0.149, 10.0.0.1.60-10.0.0.199
/// - 4 classes to compose:
/// server1 and server2 for each HA server
/// option[93].hex == 0x0009 aka telephones
/// option[93].hex == 0x0007 aka computers
///
const char* CONFIGS[] = {
// Configuration 0
"{ \"interfaces-config\": {"
......@@ -211,7 +222,58 @@ const char* CONFIGS[] = {
" \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ],"
" \"require-client-classes\": [ \"pxe2\" ]"
" } ]"
"}"
"}",
// Configuration 4
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"valid-lifetime\": 600,"
"\"client-classes\": ["
"{"
" \"name\": \"server1\""
"},"
"{"
" \"name\": \"server2\""
"},"
"{"
" \"name\": \"telephones\","
" \"test\": \"option[93].hex == 0x0009\""
"},"
"{"
" \"name\": \"computers\","
" \"test\": \"option[93].hex == 0x0007\""
"},"
"{"
" \"name\": \"server1_and_telephones\","
" \"test\": \"member('server1') and member('telephones')\""
"},"
"{"
" \"name\": \"server1_and_computers\","
" \"test\": \"member('server1') and member('computers')\""
"},"
"{"
" \"name\": \"server2_and_telephones\","
" \"test\": \"member('server2') and member('telephones')\""
"},"
"{"
" \"name\": \"server2_and_computers\","
" \"test\": \"member('server2') and member('computers')\""
"} ],"
"\"subnet4\": [ { "
" \"subnet\": \"10.0.0.0/24\", "
" \"id\": 1,"
" \"pools\": [ "
" { \"pool\": \"10.0.0.10-10.0.0.49\","
" \"client-class\": \"server1_and_telephones\" },"
" { \"pool\": \"10.0.0.60-10.0.0.99\","
" \"client-class\": \"server1_and_computers\" },"
" { \"pool\": \"10.0.0.110-10.0.0.149\","
" \"client-class\": \"server2_and_telephones\" },"
" { \"pool\": \"10.0.0.160-10.0.0.199\","
" \"client-class\": \"server2_and_computers\" } ]"
" } ]"
"}",
};
......@@ -633,6 +695,106 @@ TEST_F(ClassifyTest, fixedFieldsInformFile32) {
testFixedFields(CONFIGS[3], DHCPINFORM, pxe, "0.0.0.0", "", "ipxe.efi");
}
// This test checks the complex membership from HA with server1 telephone.
TEST_F(ClassifyTest, server1Telephone) {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(CONFIGS[4], *client.getServer());
// Add option.
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0009));
client.addExtraOption(pxe);
// Add server1
client.addClass("server1");
// Get an address
client.doDORA();
// Check response.
Pkt4Ptr resp = client.getContext().response_;
ASSERT_TRUE(resp);
// The address is from the first pool.
EXPECT_EQ("10.0.0.10", resp->getYiaddr().toText());
}
// This test checks the complex membership from HA with server1 computer.
TEST_F(ClassifyTest, server1computer) {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(CONFIGS[4], *client.getServer());
// Add option.
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0007));
client.addExtraOption(pxe);
// Add server1
client.addClass("server1");
// Get an address
client.doDORA();
// Check response.
Pkt4Ptr resp = client.getContext().response_;
ASSERT_TRUE(resp);
// The address is from the second pool.
EXPECT_EQ("10.0.0.60", resp->getYiaddr().toText());
}
// This test checks the complex membership from HA with server2 telephone.
TEST_F(ClassifyTest, server2Telephone) {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(CONFIGS[4], *client.getServer());
// Add option.
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0009));
client.addExtraOption(pxe);
// Add server2
client.addClass("server2");
// Get an address
client.doDORA();
// Check response.
Pkt4Ptr resp = client.getContext().response_;
ASSERT_TRUE(resp);
// The address is from the third pool.
EXPECT_EQ("10.0.0.110", resp->getYiaddr().toText());
}
// This test checks the complex membership from HA with server2 computer.
TEST_F(ClassifyTest, server2computer) {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(CONFIGS[4], *client.getServer());
// Add option.
OptionPtr pxe(new OptionInt<uint16_t>(Option::V4, 93, 0x0007));
client.addExtraOption(pxe);
// Add server2
client.addClass("server2");
// Get an address
client.doDORA();
// Check response.
Pkt4Ptr resp = client.getContext().response_;
ASSERT_TRUE(resp);
// The address is from the forth pool.
EXPECT_EQ("10.0.0.160", resp->getYiaddr().toText());
}
// This test checks the precedence order in required evaluation.
// This order is: shared-network > subnet > pools
TEST_F(ClassifyTest, precedenceNone) {
......
// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -238,6 +238,14 @@ Dhcp4Client::appendExtraOptions() {
}
}
void
Dhcp4Client::appendClasses() {
for (ClientClasses::const_iterator cclass = classes_.cbegin();
cclass != classes_.cend(); ++cclass) {
context_.query_->addClass(*cclass);
}
}
void
Dhcp4Client::doDiscover(const boost::shared_ptr<IOAddress>& requested_addr) {
context_.query_ = createMsg(DHCPDISCOVER);
......@@ -255,6 +263,7 @@ Dhcp4Client::doDiscover(const boost::shared_ptr<IOAddress>& requested_addr) {
context_.query_->setCiaddr(ciaddr_.get());
}
appendExtraOptions();
appendClasses();
// Send the message to the server.
sendMsg(context_.query_);
......@@ -277,6 +286,8 @@ Dhcp4Client::doInform(const bool set_ciaddr) {
appendPRL();
// Any other options to be sent by a client.
appendExtraOptions();
// Add classes.
appendClasses();
// The client sending a DHCPINFORM message has an IP address obtained
// by some other means, e.g. static configuration. The lease which we
// are using here is most likely set by the createLease method.
......@@ -396,6 +407,8 @@ Dhcp4Client::doRequest() {
appendClientId();
// Any other options to be sent by a client.
appendExtraOptions();
// Add classes.
appendClasses();
// Send the message to the server.
sendMsg(context_.query_);
// Expect response.
......@@ -518,6 +531,12 @@ Dhcp4Client::sendMsg(const Pkt4Ptr& msg) {
msg_copy->setRemoteAddr(msg->getLocalAddr());
msg_copy->setLocalAddr(dest_addr_);
msg_copy->setIface(iface_name_);
// Copy classes
const ClientClasses& classes = msg->getClasses();
for (ClientClasses::const_iterator cclass = classes.cbegin();
cclass != classes.cend(); ++cclass) {
msg_copy->addClass(*cclass);
}
srv_->fakeReceive(msg_copy);
srv_->run();
}
......@@ -536,6 +555,13 @@ Dhcp4Client::addExtraOption(const OptionPtr& opt) {
extra_options_.insert(std::make_pair(opt->getType(), opt));
}
void
Dhcp4Client::addClass(const ClientClass& client_class) {
if (!classes_.contains(client_class)) {
classes_.insert(client_class);
}
}
} // end of namespace isc::dhcp::test
} // end of namespace isc::dhcp
} // end of namespace isc
// Copyright (C) 2014-2016 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -369,12 +369,22 @@ public:
/// @param opt additional option to be sent
void addExtraOption(const OptionPtr& opt);
/// @brief Add a client class.
///
/// @param client_class name of the class to be added.
void addClass(const ClientClass& client_class);
private:
/// @brief Appends extra options, previously added with addExtraOption()
///
/// @brief Copies options from extra_options_ into outgoing message
void appendExtraOptions();
/// @brief Appends extra classes, previously added with addClass()
///
/// @brief Add client classes from classes_ to incoming message
void appendClasses();
/// @brief Creates and adds Requested IP Address option to the client's
/// query.
///
......@@ -491,6 +501,9 @@ private:
/// @brief Extra options the client will send.
OptionCollection extra_options_;
/// @brief Extra classes to add to the query.
ClientClasses classes_;
};
} // end of namespace isc::dhcp::test
......
......@@ -46,6 +46,27 @@ namespace {
/// the 'foo' value.
/// - There is one subnet specified 2001:db8:1::/48 with pool of
/// IPv6 addresses.
///
/// - Configuration 1:
/// - Used for complex membership (example taken from HA)
/// - 1 subnet: 2001:db8:1::/48
/// - 4 pools: 2001:db8:1:1::/64, 2001:db8:1:2::/64,
/// 2001:db8:1:3::/64 and 2001:db8:1:4::/64
/// - 4 classes to compose:
/// server1 and server2 for each HA server
/// option 1234 'foo' aka telephones
/// option 1234 'bar' aka computers
///
/// - Configuration 2:
/// - Used for complex membership (example taken from HA) and pd-pools
/// - 1 subnet: 2001:db8::/32
/// - 4 pd-pools: 2001:db8:1::/48, 2001:db8:2::/48,
/// 2001:db8:3::/48 and 2001:db8:4::/48
/// - 4 classes to compose:
/// server1 and server2 for each HA server
/// option 1234 'foo' aka telephones
/// option 1234 'bar' aka computers
///
const char* CONFIGS[] = {
// Configuration 0
"{ \"interfaces-config\": {"
......@@ -104,7 +125,128 @@ const char* CONFIGS[] = {
" \"client-classes\": [ \"reserved-class1\", \"reserved-class2\" ]"
" } ]"
" } ],"
"\"valid-lifetime\": 4000 }",
// Configuration 1
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"option-def\": [ "
"{"
" \"name\": \"host-name\","
" \"code\": 1234,"
" \"type\": \"string\""
"} ],"
"\"client-classes\": ["
"{"
" \"name\": \"server1\""
"},"
"{"
" \"name\": \"server2\""
"},"
"{"
" \"name\": \"telephones\","
" \"test\": \"option[host-name].text == 'foo'\""
"},"
"{"
" \"name\": \"computers\","
" \"test\": \"option[host-name].text == 'bar'\""
"},"
"{"
" \"name\": \"server1_and_telephones\","
" \"test\": \"member('server1') and member('telephones')\""
"},"
"{"
" \"name\": \"server1_and_computers\","
" \"test\": \"member('server1') and member('computers')\""
"},"
"{"
" \"name\": \"server2_and_telephones\","
" \"test\": \"member('server2') and member('telephones')\""
"},"
"{"
" \"name\": \"server2_and_computers\","
" \"test\": \"member('server2') and member('computers')\""
"}"
"],"
"\"subnet6\": [ "
"{ \"subnet\": \"2001:db8:1::/48\", "
" \"interface\": \"eth1\","
" \"pools\": [ "
" { \"pool\": \"2001:db8:1:1::/64\","
" \"client-class\": \"server1_and_telephones\" },"
" { \"pool\": \"2001:db8:1:2::/64\","
" \"client-class\": \"server1_and_computers\" },"
" { \"pool\": \"2001:db8:1:3::/64\","
" \"client-class\": \"server2_and_telephones\" },"
" { \"pool\": \"2001:db8:1:4::/64\","
" \"client-class\": \"server2_and_computers\" } ]"
" } ],"
"\"valid-lifetime\": 4000 }",
// Configuration 2
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"\"preferred-lifetime\": 3000,"
"\"rebind-timer\": 2000, "
"\"renew-timer\": 1000, "
"\"option-def\": [ "
"{"
" \"name\": \"host-name\","
" \"code\": 1234,"
" \"type\": \"string\""
"} ],"
"\"client-classes\": ["
"{"
" \"name\": \"server1\""
"},"
"{"
" \"name\": \"server2\""
"},"
"{"
" \"name\": \"telephones\","
" \"test\": \"option[host-name].text == 'foo'\""
"},"
"{"
" \"name\": \"computers\","
" \"test\": \"option[host-name].text == 'bar'\""
"},"
"{"
" \"name\": \"server1_and_telephones\","
" \"test\": \"member('server1') and member('telephones')\""
"},"
"{"
" \"name\": \"server1_and_computers\","
" \"test\": \"member('server1') and member('computers')\""
"},"
"{"
" \"name\": \"server2_and_telephones\","
" \"test\": \"member('server2') and member('telephones')\""
"},"
"{"
" \"name\": \"server2_and_computers\","
" \"test\": \"member('server2') and member('computers')\""
"}"
"],"
"\"subnet6\": [ "
"{ \"subnet\": \"2001:db8::/32\", "
" \"interface\": \"eth1\","
" \"pools\": [ "
" { \"pool\": \"2001:db8:1::/48\","
" \"client-class\": \"server1_and_telephones\" },"
" { \"pool\": \"2001:db8:2::/48\","
" \"client-class\": \"server1_and_computers\" },"
" { \"pool\": \"2001:db8:3::/48\","
" \"client-class\": \"server2_and_telephones\" },"
" { \"pool\": \"2001:db8:4::/48\","
" \"client-class\": \"server2_and_computers\" } ]"
" } ],"
"\"valid-lifetime\": 4000 }"
};
/// @brief Test fixture class for testing client classification by the
......@@ -1551,4 +1693,32 @@ TEST_F(ClassifyTest, precedenceNetwork) {
EXPECT_EQ("2001:db8:1::3", addrs[0].toText());
}
// This test checks the complex membership from HA with server1 telephone.
TEST_F(ClassifyTest, server1Telephone) {
// Create a client.
Dhcp6Client client;
client.setInterface("eth1");
ASSERT_NO_THROW(client.requestAddress(0xabca0));
// Add option.
OptionStringPtr hostname(new OptionString(Option::V6, 1234, "foo"));
client.addExtraOption(hostname);
// Add server1
client.addClass("server1");
// Load the config and perform a SARR
configure(CONFIGS[1], *client.getServer());
ASSERT_NO_THROW(client.doSARR());
// Check response
Pkt6Ptr resp = client.getContext().response_;
ASSERT_TRUE(resp);
// The address is from the first pool.
ASSERT_EQ(1, client.getLeaseNum());
Lease6 lease_client = client.getLease(0);
EXPECT_EQ("2001:db8:1:1::", lease_client.addr_.toText());
}
} // end of anonymous namespace
// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -423,6 +423,12 @@ Dhcp6Client::createMsg(const uint8_t msg_type) {
}
}
// Add classes.
for (ClientClasses::const_iterator cclass = classes_.cbegin();
cclass != classes_.cend(); ++cclass) {
msg->addClass(*cclass);
}
return (msg);
}
......@@ -930,6 +936,13 @@ Dhcp6Client::sendMsg(const Pkt6Ptr& msg) {
msg_copy->setLocalAddr(dest_addr_);
msg_copy->setIface(iface_name_);
// Copy classes
const ClientClasses& classes = msg->getClasses();
for (ClientClasses::const_iterator cclass = classes.cbegin();
cclass != classes.cend(); ++cclass) {
msg_copy->addClass(*cclass);
}
srv_->fakeReceive(msg_copy);
srv_->run();
}
......@@ -969,6 +982,18 @@ Dhcp6Client::clearExtraOptions() {
extra_options_.clear();
}
void
Dhcp6Client::addClass(const ClientClass& client_class) {
if (!classes_.contains(client_class)) {
classes_.insert(client_class);
}
}
void
Dhcp6Client::clearClasses() {
classes_.clear();
}
void
Dhcp6Client::printConfiguration() const {
......
// Copyright (C) 2014-2017 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
......@@ -753,6 +753,14 @@ public:
/// @brief Configures the client to not send any extra options.
void clearExtraOptions();
/// @brief Add a client class.
///
/// @param client_class name of the class to be added.
void addClass(const ClientClass& client_class);
/// @brief Configures the client to not add client classes.
void clearClasses();
/// @brief Debugging method the prints currently held configuration
///
/// @todo: This is mostly useful when debugging tests. This method
......@@ -927,6 +935,9 @@ private:
/// @brief Interface id.
OptionPtr interface_id_;
/// @brief Extra classes to add to the query.
ClientClasses classes_;
};
} // end of namespace isc::dhcp::test
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment