mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 21:45:37 +00:00
[master] Finished merge of trac4523 (vendor options in Renew and Rebind)
This commit is contained in:
@@ -2331,6 +2331,7 @@ Dhcpv6Srv::processRenew(const Pkt6Ptr& renew) {
|
|||||||
buildCfgOptionList(renew, ctx, co_list);
|
buildCfgOptionList(renew, ctx, co_list);
|
||||||
appendDefaultOptions(renew, reply, co_list);
|
appendDefaultOptions(renew, reply, co_list);
|
||||||
appendRequestedOptions(renew, reply, co_list);
|
appendRequestedOptions(renew, reply, co_list);
|
||||||
|
appendRequestedVendorOptions(renew, reply, ctx, co_list);
|
||||||
|
|
||||||
processClientFqdn(renew, reply, ctx);
|
processClientFqdn(renew, reply, ctx);
|
||||||
extendLeases(renew, reply, ctx);
|
extendLeases(renew, reply, ctx);
|
||||||
@@ -2356,6 +2357,7 @@ Dhcpv6Srv::processRebind(const Pkt6Ptr& rebind) {
|
|||||||
buildCfgOptionList(rebind, ctx, co_list);
|
buildCfgOptionList(rebind, ctx, co_list);
|
||||||
appendDefaultOptions(rebind, reply, co_list);
|
appendDefaultOptions(rebind, reply, co_list);
|
||||||
appendRequestedOptions(rebind, reply, co_list);
|
appendRequestedOptions(rebind, reply, co_list);
|
||||||
|
appendRequestedVendorOptions(rebind, reply, ctx, co_list);
|
||||||
|
|
||||||
processClientFqdn(rebind, reply, ctx);
|
processClientFqdn(rebind, reply, ctx);
|
||||||
extendLeases(rebind, reply, ctx);
|
extendLeases(rebind, reply, ctx);
|
||||||
@@ -2389,6 +2391,7 @@ Dhcpv6Srv::processConfirm(const Pkt6Ptr& confirm) {
|
|||||||
buildCfgOptionList(confirm, ctx, co_list);
|
buildCfgOptionList(confirm, ctx, co_list);
|
||||||
appendDefaultOptions(confirm, reply, co_list);
|
appendDefaultOptions(confirm, reply, co_list);
|
||||||
appendRequestedOptions(confirm, reply, co_list);
|
appendRequestedOptions(confirm, reply, co_list);
|
||||||
|
appendRequestedVendorOptions(confirm, reply, ctx, co_list);
|
||||||
// Indicates if at least one address has been verified. If no addresses
|
// Indicates if at least one address has been verified. If no addresses
|
||||||
// are verified it means that the client has sent no IA_NA options
|
// are verified it means that the client has sent no IA_NA options
|
||||||
// or no IAAddr options and that client's message has to be discarded.
|
// or no IAAddr options and that client's message has to be discarded.
|
||||||
@@ -2788,6 +2791,9 @@ Dhcpv6Srv::processInfRequest(const Pkt6Ptr& inf_request) {
|
|||||||
// Try to assign options that were requested by the client.
|
// Try to assign options that were requested by the client.
|
||||||
appendRequestedOptions(inf_request, reply, co_list);
|
appendRequestedOptions(inf_request, reply, co_list);
|
||||||
|
|
||||||
|
// Try to assigne vendor options that were requested by the client.
|
||||||
|
appendRequestedVendorOptions(inf_request, reply, ctx, co_list);
|
||||||
|
|
||||||
return (reply);
|
return (reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -6,11 +6,13 @@
|
|||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <dhcp/dhcp6.h>
|
#include <dhcp/dhcp6.h>
|
||||||
|
#include <dhcp/docsis3_option_defs.h>
|
||||||
#include <dhcp/option_custom.h>
|
#include <dhcp/option_custom.h>
|
||||||
#include <dhcp/option6_ia.h>
|
#include <dhcp/option6_ia.h>
|
||||||
#include <dhcp/option6_iaaddr.h>
|
#include <dhcp/option6_iaaddr.h>
|
||||||
#include <dhcp/option6_status_code.h>
|
#include <dhcp/option6_status_code.h>
|
||||||
#include <dhcp/option_int_array.h>
|
#include <dhcp/option_int_array.h>
|
||||||
|
#include <dhcp/option_vendor.h>
|
||||||
#include <dhcp/pkt6.h>
|
#include <dhcp/pkt6.h>
|
||||||
#include <dhcpsrv/lease.h>
|
#include <dhcpsrv/lease.h>
|
||||||
#include <dhcpsrv/pool.h>
|
#include <dhcpsrv/pool.h>
|
||||||
@@ -100,6 +102,7 @@ Dhcp6Client::Dhcp6Client() :
|
|||||||
srv_(boost::shared_ptr<NakedDhcpv6Srv>(new NakedDhcpv6Srv(0))),
|
srv_(boost::shared_ptr<NakedDhcpv6Srv>(new NakedDhcpv6Srv(0))),
|
||||||
use_relay_(false),
|
use_relay_(false),
|
||||||
use_oro_(false),
|
use_oro_(false),
|
||||||
|
use_docsis_oro_(false),
|
||||||
use_client_id_(true),
|
use_client_id_(true),
|
||||||
use_rapid_commit_(false),
|
use_rapid_commit_(false),
|
||||||
client_ias_(),
|
client_ias_(),
|
||||||
@@ -116,6 +119,7 @@ Dhcp6Client::Dhcp6Client(boost::shared_ptr<NakedDhcpv6Srv>& srv) :
|
|||||||
srv_(srv),
|
srv_(srv),
|
||||||
use_relay_(false),
|
use_relay_(false),
|
||||||
use_oro_(false),
|
use_oro_(false),
|
||||||
|
use_docsis_oro_(false),
|
||||||
use_client_id_(true),
|
use_client_id_(true),
|
||||||
use_rapid_commit_(false),
|
use_rapid_commit_(false),
|
||||||
client_ias_(),
|
client_ias_(),
|
||||||
@@ -396,6 +400,15 @@ Dhcp6Client::createMsg(const uint8_t msg_type) {
|
|||||||
msg->addOption(oro);
|
msg->addOption(oro);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (use_docsis_oro_) {
|
||||||
|
OptionUint16ArrayPtr vendor_oro(new OptionUint16Array(Option::V6,
|
||||||
|
DOCSIS3_V6_ORO));
|
||||||
|
vendor_oro->setValues(docsis_oro_);
|
||||||
|
OptionPtr vendor(new OptionVendor(Option::V6, 4491));
|
||||||
|
vendor->addOption(vendor_oro);
|
||||||
|
msg->addOption(vendor);
|
||||||
|
}
|
||||||
|
|
||||||
// If there are any custom options specified, add them all to the message.
|
// If there are any custom options specified, add them all to the message.
|
||||||
if (!extra_options_.empty()) {
|
if (!extra_options_.empty()) {
|
||||||
for (OptionCollection::iterator opt = extra_options_.begin();
|
for (OptionCollection::iterator opt = extra_options_.begin();
|
||||||
|
@@ -27,7 +27,7 @@ namespace test {
|
|||||||
/// @brief DHCPv6 client used for unit testing.
|
/// @brief DHCPv6 client used for unit testing.
|
||||||
///
|
///
|
||||||
/// This class implements a DHCPv6 "client" which interoperates with the
|
/// This class implements a DHCPv6 "client" which interoperates with the
|
||||||
/// @c NakedDhcpv6Srv class. It calls @c NakedDhcpv6Srv::fakeRecive to
|
/// @c NakedDhcpv6Srv class. It calls @c NakedDhcpv6Srv::fakeReceive to
|
||||||
/// deliver client messages to the server for processing. The server places
|
/// deliver client messages to the server for processing. The server places
|
||||||
/// the response in the @c NakedDhcpv6Srv::fake_sent_ container. The client
|
/// the response in the @c NakedDhcpv6Srv::fake_sent_ container. The client
|
||||||
/// pops messages from this container which simulates reception of the
|
/// pops messages from this container which simulates reception of the
|
||||||
@@ -684,6 +684,25 @@ public:
|
|||||||
oro_.push_back(option_code);
|
oro_.push_back(option_code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Controls whether the client will send DOCSIS vendor ORO
|
||||||
|
///
|
||||||
|
/// The actual content of the ORO is specified in docsis_oro_.
|
||||||
|
/// It is useful to split the actual content and the ORO sending
|
||||||
|
/// decision, so we could test cases of sending empty ORO.
|
||||||
|
/// @param send controls whether ORO will be sent or not.
|
||||||
|
void useDocsisORO(bool send) {
|
||||||
|
use_docsis_oro_ = send;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Instructs client to request specified option in DOCSIS
|
||||||
|
/// vendor ORO
|
||||||
|
///
|
||||||
|
/// @param option_code client will request this option code
|
||||||
|
void requestDocsisOption(uint16_t option_code) {
|
||||||
|
use_docsis_oro_ = true;
|
||||||
|
docsis_oro_.push_back(option_code);
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief returns client-id
|
/// @brief returns client-id
|
||||||
/// @return client-id
|
/// @return client-id
|
||||||
DuidPtr getDuid() const {
|
DuidPtr getDuid() const {
|
||||||
@@ -840,6 +859,7 @@ private:
|
|||||||
bool use_relay_; ///< Enable relaying messages to the server.
|
bool use_relay_; ///< Enable relaying messages to the server.
|
||||||
|
|
||||||
bool use_oro_; ///< Conth
|
bool use_oro_; ///< Conth
|
||||||
|
bool use_docsis_oro_;
|
||||||
bool use_client_id_;
|
bool use_client_id_;
|
||||||
bool use_rapid_commit_;
|
bool use_rapid_commit_;
|
||||||
|
|
||||||
@@ -852,6 +872,12 @@ private:
|
|||||||
/// to true. See @ref sendORO for details.
|
/// to true. See @ref sendORO for details.
|
||||||
std::vector<uint16_t> oro_;
|
std::vector<uint16_t> oro_;
|
||||||
|
|
||||||
|
/// @brief List of DOCSIS vendor options to be requested
|
||||||
|
///
|
||||||
|
/// Content of this vector will be sent as DOCSIS vendor ORO if
|
||||||
|
/// use_docsis_oro_ is set to true. See @ref sendDocsisORO for details.
|
||||||
|
std::vector<uint16_t> docsis_oro_;
|
||||||
|
|
||||||
/// @brief forced (Overridden) value of the server-id option (may be NULL)
|
/// @brief forced (Overridden) value of the server-id option (may be NULL)
|
||||||
OptionPtr forced_server_id_;
|
OptionPtr forced_server_id_;
|
||||||
|
|
||||||
|
@@ -240,7 +240,7 @@ TEST_F(Dhcpv6SrvTest, basic) {
|
|||||||
});
|
});
|
||||||
srv.reset();
|
srv.reset();
|
||||||
ASSERT_NO_THROW({
|
ASSERT_NO_THROW({
|
||||||
// open an unpriviledged port
|
// open an unprivileged port
|
||||||
srv.reset(new NakedDhcpv6Srv(DHCP6_SERVER_PORT + 10000));
|
srv.reset(new NakedDhcpv6Srv(DHCP6_SERVER_PORT + 10000));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1631,7 +1631,7 @@ TEST_F(Dhcpv6SrvTest, vendorOptionsORO) {
|
|||||||
// check if we get response at all
|
// check if we get response at all
|
||||||
ASSERT_TRUE(adv);
|
ASSERT_TRUE(adv);
|
||||||
|
|
||||||
// We did not include any vendor opts in SOLCIT, so there should be none
|
// We did not include any vendor opts in SOLICIT, so there should be none
|
||||||
// in ADVERTISE.
|
// in ADVERTISE.
|
||||||
ASSERT_FALSE(adv->getOption(D6O_VENDOR_OPTS));
|
ASSERT_FALSE(adv->getOption(D6O_VENDOR_OPTS));
|
||||||
|
|
||||||
@@ -2449,8 +2449,8 @@ TEST_F(Dhcpv6SrvTest, rsoo2relays) {
|
|||||||
opt = createRSOO(rsoo2, 2); // use 0x2 as payload
|
opt = createRSOO(rsoo2, 2); // use 0x2 as payload
|
||||||
relay2.options_.insert(make_pair(opt->getType(), opt));
|
relay2.options_.insert(make_pair(opt->getType(), opt));
|
||||||
|
|
||||||
// The relays ecapsulate packet in this order: relay1, relay2, but the server
|
// The relays encapsulate packet in this order: relay1, relay2,
|
||||||
// decapsulates the packet in reverse order.
|
// but the server decapsulates the packet in reverse order.
|
||||||
client.relay_info_.push_back(relay2);
|
client.relay_info_.push_back(relay2);
|
||||||
client.relay_info_.push_back(relay1);
|
client.relay_info_.push_back(relay1);
|
||||||
|
|
||||||
@@ -2651,7 +2651,7 @@ TEST_F(Dhcpv6SrvTest, receiveParseFailedStat) {
|
|||||||
// fakeReceive()
|
// fakeReceive()
|
||||||
srv.run();
|
srv.run();
|
||||||
|
|
||||||
// All expected statstics must be present.
|
// All expected statistics must be present.
|
||||||
pkt6_rcvd = mgr.getObservation("pkt6-received");
|
pkt6_rcvd = mgr.getObservation("pkt6-received");
|
||||||
parse_fail = mgr.getObservation("pkt6-parse-failed");
|
parse_fail = mgr.getObservation("pkt6-parse-failed");
|
||||||
recv_drop = mgr.getObservation("pkt6-receive-drop");
|
recv_drop = mgr.getObservation("pkt6-receive-drop");
|
||||||
|
@@ -7,6 +7,9 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <asiolink/io_address.h>
|
#include <asiolink/io_address.h>
|
||||||
#include <cc/data.h>
|
#include <cc/data.h>
|
||||||
|
#include <dhcp/docsis3_option_defs.h>
|
||||||
|
#include <dhcp/option_string.h>
|
||||||
|
#include <dhcp/option_vendor.h>
|
||||||
#include <dhcp/tests/iface_mgr_test_config.h>
|
#include <dhcp/tests/iface_mgr_test_config.h>
|
||||||
#include <dhcp6/json_config_parser.h>
|
#include <dhcp6/json_config_parser.h>
|
||||||
#include <dhcp6/tests/dhcp6_message_test.h>
|
#include <dhcp6/tests/dhcp6_message_test.h>
|
||||||
@@ -60,6 +63,12 @@ namespace {
|
|||||||
/// - address pool: 2001:db8:1::/64
|
/// - address pool: 2001:db8:1::/64
|
||||||
/// - prefix pool: 3000::/72
|
/// - prefix pool: 3000::/72
|
||||||
///
|
///
|
||||||
|
/// - Configuration 7:
|
||||||
|
/// - only addresses (no prefixes)
|
||||||
|
/// - 2 subnets with 2001:db8:1::/64 and 2001:db8:2::/64
|
||||||
|
/// - 1 subnet for eth0 and 1 subnet for eth1
|
||||||
|
/// - DOCSIS vendor config file sub-option
|
||||||
|
///
|
||||||
const char* REBIND_CONFIGS[] = {
|
const char* REBIND_CONFIGS[] = {
|
||||||
// Configuration 0
|
// Configuration 0
|
||||||
"{ \"interfaces-config\": {"
|
"{ \"interfaces-config\": {"
|
||||||
@@ -221,6 +230,32 @@ const char* REBIND_CONFIGS[] = {
|
|||||||
" \"interface-id\": \"\","
|
" \"interface-id\": \"\","
|
||||||
" \"interface\": \"eth0\""
|
" \"interface\": \"eth0\""
|
||||||
" } ],"
|
" } ],"
|
||||||
|
"\"valid-lifetime\": 4000 }",
|
||||||
|
|
||||||
|
// Configuration 7
|
||||||
|
"{ \"interfaces-config\": {"
|
||||||
|
" \"interfaces\": [ \"*\" ]"
|
||||||
|
"},"
|
||||||
|
"\"preferred-lifetime\": 3000,"
|
||||||
|
"\"rebind-timer\": 2000, "
|
||||||
|
"\"renew-timer\": 1000, "
|
||||||
|
"\"option-data\": [ {"
|
||||||
|
" \"name\": \"config-file\","
|
||||||
|
" \"space\": \"vendor-4491\","
|
||||||
|
" \"data\": \"normal_erouter_v6.cm\""
|
||||||
|
"}],"
|
||||||
|
"\"subnet6\": [ { "
|
||||||
|
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
|
||||||
|
" \"subnet\": \"2001:db8:1::/48\", "
|
||||||
|
" \"interface-id\": \"\","
|
||||||
|
" \"interface\": \"eth0\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ],"
|
||||||
|
" \"subnet\": \"2001:db8:2::/48\", "
|
||||||
|
" \"interface-id\": \"\","
|
||||||
|
" \"interface\": \"eth1\""
|
||||||
|
" } ],"
|
||||||
"\"valid-lifetime\": 4000 }"
|
"\"valid-lifetime\": 4000 }"
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -895,5 +930,78 @@ TEST_F(RebindTest, requestAddressInRebind) {
|
|||||||
EXPECT_EQ(STATUS_Success, client.getStatusCode(1234));
|
EXPECT_EQ(STATUS_Success, client.getStatusCode(1234));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies that the client can request the DOCSIS sub-options.
|
||||||
|
TEST_F(RebindTest, docsisORO) {
|
||||||
|
Dhcp6Client client;
|
||||||
|
// Configure client to request IA_NA.
|
||||||
|
client.requestAddress();
|
||||||
|
// Configure the DOCSIS vendor ORO for 32, 33, 34, 37 and 38.
|
||||||
|
client.requestDocsisOption(DOCSIS3_V6_TFTP_SERVERS);
|
||||||
|
client.requestDocsisOption(DOCSIS3_V6_CONFIG_FILE);
|
||||||
|
client.requestDocsisOption(DOCSIS3_V6_SYSLOG_SERVERS);
|
||||||
|
client.requestDocsisOption(DOCSIS3_V6_TIME_SERVERS);
|
||||||
|
client.requestDocsisOption(DOCSIS3_V6_TIME_OFFSET);
|
||||||
|
// Don't add it for now.
|
||||||
|
client.useDocsisORO(false);
|
||||||
|
// Make 4-way exchange to get the lease.
|
||||||
|
ASSERT_NO_FATAL_FAILURE(requestLease(REBIND_CONFIGS[7], 2, client));
|
||||||
|
// Keep the client's lease for future reference.
|
||||||
|
Lease6 lease_client = client.getLease(0);
|
||||||
|
|
||||||
|
// Send Rebind message to the server.
|
||||||
|
ASSERT_NO_THROW(client.doRebind());
|
||||||
|
// The client should still have one lease which belong to one of the
|
||||||
|
// subnets.
|
||||||
|
ASSERT_EQ(1, client.getLeaseNum());
|
||||||
|
Lease6 lease_client2 = client.getLease(0);
|
||||||
|
ASSERT_TRUE(CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->
|
||||||
|
selectSubnet(lease_client2.addr_, ClientClasses()));
|
||||||
|
// The client's lease should have been extended. The client will
|
||||||
|
// update the cltt to current time when the lease gets extended.
|
||||||
|
ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000);
|
||||||
|
// Make sure, that the client's lease matches the lease held by the
|
||||||
|
// server.
|
||||||
|
Lease6Ptr lease_server2 = checkLease(lease_client2);
|
||||||
|
EXPECT_TRUE(lease_server2);
|
||||||
|
// No vendor option was included in the renew so there should be none
|
||||||
|
// in the received configuration.
|
||||||
|
OptionPtr opt = client.config_.findOption(D6O_VENDOR_OPTS);
|
||||||
|
ASSERT_FALSE(opt);
|
||||||
|
|
||||||
|
// Add a DOCSIS ORO.
|
||||||
|
client.useDocsisORO(true);
|
||||||
|
// Send Rebind message to the server.
|
||||||
|
ASSERT_NO_THROW(client.doRebind());
|
||||||
|
// The client should still have one lease which belong to one of the
|
||||||
|
// subnets.
|
||||||
|
ASSERT_EQ(1, client.getLeaseNum());
|
||||||
|
lease_client2 = client.getLease(0);
|
||||||
|
ASSERT_TRUE(CfgMgr::instance().getCurrentCfg()->getCfgSubnets6()->
|
||||||
|
selectSubnet(lease_client2.addr_, ClientClasses()));
|
||||||
|
// The client's lease should have been extended. The client will
|
||||||
|
// update the cltt to current time when the lease gets extended.
|
||||||
|
ASSERT_GE(lease_client2.cltt_ - lease_client.cltt_, 1000);
|
||||||
|
// Make sure, that the client's lease matches the lease held by the
|
||||||
|
// server.
|
||||||
|
lease_server2 = checkLease(lease_client2);
|
||||||
|
EXPECT_TRUE(lease_server2);
|
||||||
|
|
||||||
|
// Verify whether there is a vendor option.
|
||||||
|
opt = client.config_.findOption(D6O_VENDOR_OPTS);
|
||||||
|
ASSERT_TRUE(opt);
|
||||||
|
// The vendor option must be a OptionVendor object.
|
||||||
|
boost::shared_ptr<OptionVendor> vendor =
|
||||||
|
boost::dynamic_pointer_cast<OptionVendor>(opt);
|
||||||
|
ASSERT_TRUE(vendor);
|
||||||
|
// The vendor-id should be DOCSIS.
|
||||||
|
EXPECT_EQ(VENDOR_ID_CABLE_LABS, vendor->getVendorId());
|
||||||
|
// There must be a config file sub-option.
|
||||||
|
opt = vendor->getOption(DOCSIS3_V6_CONFIG_FILE);
|
||||||
|
// With the expected content.
|
||||||
|
OptionStringPtr config_file =
|
||||||
|
boost::dynamic_pointer_cast<OptionString>(opt);
|
||||||
|
ASSERT_TRUE(opt);
|
||||||
|
EXPECT_EQ("normal_erouter_v6.cm", config_file->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
} // end of anonymous namespace
|
} // end of anonymous namespace
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
|
// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
|
||||||
//
|
//
|
||||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
// 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
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
@@ -7,9 +7,13 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
#include <asiolink/io_address.h>
|
#include <asiolink/io_address.h>
|
||||||
#include <cc/data.h>
|
#include <cc/data.h>
|
||||||
|
#include <dhcp/docsis3_option_defs.h>
|
||||||
|
#include <dhcp/option_string.h>
|
||||||
|
#include <dhcp/option_vendor.h>
|
||||||
#include <dhcp/tests/iface_mgr_test_config.h>
|
#include <dhcp/tests/iface_mgr_test_config.h>
|
||||||
#include <dhcp6/json_config_parser.h>
|
#include <dhcp6/json_config_parser.h>
|
||||||
#include <dhcp6/tests/dhcp6_message_test.h>
|
#include <dhcp6/tests/dhcp6_message_test.h>
|
||||||
|
#include <boost/pointer_cast.hpp>
|
||||||
|
|
||||||
using namespace isc;
|
using namespace isc;
|
||||||
using namespace isc::asiolink;
|
using namespace isc::asiolink;
|
||||||
@@ -35,6 +39,11 @@ namespace {
|
|||||||
/// - address pool: 2001:db8:1::/64
|
/// - address pool: 2001:db8:1::/64
|
||||||
/// - prefix pool: 3000::/72
|
/// - prefix pool: 3000::/72
|
||||||
///
|
///
|
||||||
|
/// - Configuration 3:
|
||||||
|
/// - only addresses (no prefixes)
|
||||||
|
/// - 1 subnet with 2001:db8:1::/64 pool
|
||||||
|
/// - DOCSIS vendor config file sub-option
|
||||||
|
///
|
||||||
const char* RENEW_CONFIGS[] = {
|
const char* RENEW_CONFIGS[] = {
|
||||||
// Configuration 0
|
// Configuration 0
|
||||||
"{ \"interfaces-config\": {"
|
"{ \"interfaces-config\": {"
|
||||||
@@ -88,7 +97,28 @@ const char* RENEW_CONFIGS[] = {
|
|||||||
" \"interface-id\": \"\","
|
" \"interface-id\": \"\","
|
||||||
" \"interface\": \"eth0\""
|
" \"interface\": \"eth0\""
|
||||||
" } ],"
|
" } ],"
|
||||||
|
"\"valid-lifetime\": 4000 }",
|
||||||
|
|
||||||
|
// Configuration 3
|
||||||
|
"{ \"interfaces-config\": {"
|
||||||
|
" \"interfaces\": [ \"*\" ]"
|
||||||
|
"},"
|
||||||
|
"\"preferred-lifetime\": 3000,"
|
||||||
|
"\"rebind-timer\": 2000, "
|
||||||
|
"\"renew-timer\": 1000, "
|
||||||
|
"\"option-data\": [ {"
|
||||||
|
" \"name\": \"config-file\","
|
||||||
|
" \"space\": \"vendor-4491\","
|
||||||
|
" \"data\": \"normal_erouter_v6.cm\""
|
||||||
|
"}],"
|
||||||
|
"\"subnet6\": [ { "
|
||||||
|
" \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ],"
|
||||||
|
" \"subnet\": \"2001:db8:1::/48\", "
|
||||||
|
" \"interface-id\": \"\","
|
||||||
|
" \"interface\": \"eth0\""
|
||||||
|
" } ],"
|
||||||
"\"valid-lifetime\": 4000 }"
|
"\"valid-lifetime\": 4000 }"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Test fixture class for testing Renew.
|
/// @brief Test fixture class for testing Renew.
|
||||||
@@ -367,5 +397,79 @@ TEST_F(RenewTest, requestAddressInRenewHint) {
|
|||||||
EXPECT_EQ(STATUS_Success, client.getStatusCode(na_iaid_));
|
EXPECT_EQ(STATUS_Success, client.getStatusCode(na_iaid_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test verifies that the client can request the DOCSIS sub-options.
|
||||||
|
TEST_F(RenewTest, docsisORO) {
|
||||||
|
Dhcp6Client client;
|
||||||
|
|
||||||
|
// Configure client to request IA_NA.
|
||||||
|
client.requestAddress(na_iaid_);
|
||||||
|
|
||||||
|
// Configure the DOCSIS vendor ORO for 32, 33, 34, 37 and 38.
|
||||||
|
client.requestDocsisOption(DOCSIS3_V6_TFTP_SERVERS);
|
||||||
|
client.requestDocsisOption(DOCSIS3_V6_CONFIG_FILE);
|
||||||
|
client.requestDocsisOption(DOCSIS3_V6_SYSLOG_SERVERS);
|
||||||
|
client.requestDocsisOption(DOCSIS3_V6_TIME_SERVERS);
|
||||||
|
client.requestDocsisOption(DOCSIS3_V6_TIME_OFFSET);
|
||||||
|
// Don't add it for now.
|
||||||
|
client.useDocsisORO(false);
|
||||||
|
|
||||||
|
// Configure the server with NA pools and DOCSIS config file.
|
||||||
|
ASSERT_NO_THROW(configure(RENEW_CONFIGS[3], *client.getServer()));
|
||||||
|
|
||||||
|
// Perform 4-way exchange.
|
||||||
|
ASSERT_NO_THROW(client.doSARR());
|
||||||
|
|
||||||
|
// Simulate aging of leases.
|
||||||
|
client.fastFwdTime(1000);
|
||||||
|
|
||||||
|
// Make sure that the client has acquired NA lease.
|
||||||
|
std::vector<Lease6> leases_client_na = client.getLeasesByType(Lease::TYPE_NA);
|
||||||
|
ASSERT_EQ(1, leases_client_na.size());
|
||||||
|
EXPECT_EQ(STATUS_Success, client.getStatusCode(na_iaid_));
|
||||||
|
|
||||||
|
// Send Renew message to the server.
|
||||||
|
ASSERT_NO_THROW(client.doRenew());
|
||||||
|
|
||||||
|
std::vector<Lease6> leases_client_na_renewed =
|
||||||
|
client.getLeasesByType(Lease::TYPE_NA);
|
||||||
|
ASSERT_EQ(1, leases_client_na_renewed.size());
|
||||||
|
EXPECT_EQ(STATUS_Success, client.getStatusCode(na_iaid_));
|
||||||
|
|
||||||
|
// No vendor option was included in the renew so there should be none
|
||||||
|
// in the received configuration.
|
||||||
|
OptionPtr opt = client.config_.findOption(D6O_VENDOR_OPTS);
|
||||||
|
ASSERT_FALSE(opt);
|
||||||
|
|
||||||
|
// Add a DOCSIS ORO.
|
||||||
|
client.useDocsisORO(true);
|
||||||
|
|
||||||
|
// Send Renew message to the server.
|
||||||
|
ASSERT_NO_THROW(client.doRenew());
|
||||||
|
|
||||||
|
leases_client_na_renewed = client.getLeasesByType(Lease::TYPE_NA);
|
||||||
|
ASSERT_EQ(1, leases_client_na_renewed.size());
|
||||||
|
EXPECT_EQ(STATUS_Success, client.getStatusCode(na_iaid_));
|
||||||
|
|
||||||
|
// Verify whether there is a vendor option.
|
||||||
|
opt = client.config_.findOption(D6O_VENDOR_OPTS);
|
||||||
|
ASSERT_TRUE(opt);
|
||||||
|
|
||||||
|
// The vendor option must be a OptionVendor object.
|
||||||
|
boost::shared_ptr<OptionVendor> vendor =
|
||||||
|
boost::dynamic_pointer_cast<OptionVendor>(opt);
|
||||||
|
ASSERT_TRUE(vendor);
|
||||||
|
|
||||||
|
// The vendor-id should be DOCSIS.
|
||||||
|
EXPECT_EQ(VENDOR_ID_CABLE_LABS, vendor->getVendorId());
|
||||||
|
|
||||||
|
// There must be a config file sub-option.
|
||||||
|
opt = vendor->getOption(DOCSIS3_V6_CONFIG_FILE);
|
||||||
|
|
||||||
|
// With the expected content.
|
||||||
|
OptionStringPtr config_file =
|
||||||
|
boost::dynamic_pointer_cast<OptionString>(opt);
|
||||||
|
ASSERT_TRUE(opt);
|
||||||
|
EXPECT_EQ("normal_erouter_v6.cm", config_file->getValue());
|
||||||
|
}
|
||||||
|
|
||||||
} // end of anonymous namespace
|
} // end of anonymous namespace
|
||||||
|
Reference in New Issue
Block a user