Commit ef4ae0b3 authored by Marcin Siodelski's avatar Marcin Siodelski
Browse files

[3173] It is possible to request IA_NA and IA_PD in a single message.

parent 646763a3
......@@ -45,6 +45,11 @@ CommandOptions::LeaseType::is(const Type lease_type) const {
return (lease_type == type_);
}
bool
CommandOptions::LeaseType::includes(const Type lease_type) const {
return (is(ADDRESS_AND_PREFIX) || (lease_type == type_));
}
void
CommandOptions::LeaseType::set(const Type lease_type) {
type_ = lease_type;
......@@ -58,6 +63,9 @@ CommandOptions::LeaseType::fromCommandLine(const std::string& cmd_line_arg) {
} else if (cmd_line_arg == "prefix-only") {
type_ = PREFIX_ONLY;
} else if (cmd_line_arg == "address-and-prefix") {
type_ = ADDRESS_AND_PREFIX;
} else {
isc_throw(isc::InvalidParameter, "value of lease-type: -e<lease-type>,"
" must be one of the following: 'address-only' or"
......@@ -72,6 +80,9 @@ CommandOptions::LeaseType::toText() const {
return ("address-only (IA_NA option added to the client's request)");
case PREFIX_ONLY:
return ("prefix-only (IA_PD option added to the client's request)");
case ADDRESS_AND_PREFIX:
return ("address-and-prefix (Both IA_NA and IA_PD options added to the"
" client's request)");
default:
isc_throw(Unexpected, "internal error: undefined lease type code when"
" returning textual representation of the lease type");
......@@ -903,10 +914,13 @@ CommandOptions::usage() const {
" having been lost. The value is given in seconds and may contain a\n"
" fractional component. The default is 1 second.\n"
"-e<lease-type>: A type of lease being requested from the server. It\n"
" may be one of the following: address-only or prefix-only. The\n"
" former indicates that the regular IP (v4 or v6) will be requested,\n"
" the latter indicates that the IPv6 prefixes will be requested. The\n"
" '-e prefix-only' must not be used with -4.\n"
" may be one of the following: address-only, prefix-only or\n"
" address-and-prefix. The address-only indicates that the regular\n"
" address (v4 or v6) will be requested. The prefix-only indicates\n"
" that the IPv6 prefix will be requested. The address-and-prefix\n"
" indicates that both IPv6 address and prefix will be requested.\n"
" The '-e prefix-only' and -'e address-and-prefix' must not be\n"
" used with -4.\n"
"-E<time-offset>: Offset of the (DHCPv4) secs field / (DHCPv6)\n"
" elapsed-time option in the (second/request) template.\n"
" The value 0 disables it.\n"
......
......@@ -43,7 +43,8 @@ public:
/// The lease type code.
enum Type {
ADDRESS_ONLY,
PREFIX_ONLY
PREFIX_ONLY,
ADDRESS_AND_PREFIX
};
LeaseType();
......@@ -60,6 +61,23 @@ public:
/// \return true if lease type is matched with the specified code.
bool is(const Type lease_type) const;
/// \brief Checks if lease type implies request for the address,
/// prefix (or both) as specified by the function argument.
///
/// This is a convenience function to check that, for the lease type
/// specified from the command line, the address or prefix
/// (IA_NA or IA_PD) option should be sent to the server.
/// For example, if user specified '-e address-and-prefix' in the
/// command line this function will return true for both ADDRESS_ONLY
/// and PREFIX_ONLY, because both address and prefix is requested from
/// the server.
///
/// \param lease_type A lease type.
///
/// \return true if the lease type implies creation of the address,
/// prefix or both as specified by the argument.
bool includes(const Type lease_type) const;
/// \brief Sets the lease type code.
///
/// \param lease_type A lease type code.
......
......@@ -103,22 +103,27 @@ TestControl::copyIaOptions(const Pkt6Ptr& pkt_from, Pkt6Ptr& pkt_to) {
isc_throw(BadValue, "NULL pointers must not be specified as arguments"
" for the copyIaOptions function");
}
OptionPtr option;
// IA_NA
if (CommandOptions::instance().getLeaseType()
.is(CommandOptions::LeaseType::ADDRESS_ONLY)) {
option = pkt_from->getOption(D6O_IA_NA);
.includes(CommandOptions::LeaseType::ADDRESS_ONLY)) {
OptionPtr option = pkt_from->getOption(D6O_IA_NA);
if (!option) {
isc_throw(OptionNotFound, "IA_NA option not found in the"
" server's response");
}
} else {
option = pkt_from->getOption(D6O_IA_PD);
pkt_to->addOption(option);
}
// IA_PD
if (CommandOptions::instance().getLeaseType()
.includes(CommandOptions::LeaseType::PREFIX_ONLY)) {
OptionPtr option = pkt_from->getOption(D6O_IA_PD);
if (!option) {
isc_throw(OptionNotFound, "IA_PD option not found in the"
" server's response");
}
pkt_to->addOption(option);
}
pkt_to->addOption(option);
}
......@@ -635,15 +640,15 @@ TestControl::openSocket() const {
uint16_t port = options.getLocalPort();
int sock = 0;
uint8_t family = (options.getIpVersion() == 6) ? AF_INET6 : AF_INET;
uint8_t family = (options.getIpVersion() == 6) ? AF_INET6 : AF_INET;
IOAddress remoteaddr(servername);
// Check for mismatch between IP option and server address
if (family != remoteaddr.getFamily()) {
isc_throw(InvalidParameter,
"Values for IP version: " <<
isc_throw(InvalidParameter,
"Values for IP version: " <<
static_cast<unsigned int>(options.getIpVersion()) <<
" and server address: " << servername << " are mismatched.");
" and server address: " << servername << " are mismatched.");
}
if (port == 0) {
......@@ -1780,11 +1785,16 @@ TestControl::sendSolicit6(const TestControlSocket& socket,
pkt6->addOption(Option::factory(Option::V6, D6O_ORO));
// Depending on the lease-type option specified, we should request
// IPv6 address (with IA_NA) or IPv6 prefix (IA_PD).
// IPv6 address (with IA_NA) or IPv6 prefix (IA_PD) or both.
// IA_NA
if (CommandOptions::instance().getLeaseType()
.is(CommandOptions::LeaseType::ADDRESS_ONLY)) {
.includes(CommandOptions::LeaseType::ADDRESS_ONLY)) {
pkt6->addOption(Option::factory(Option::V6, D6O_IA_NA));
} else {
}
// IA_PD
if (CommandOptions::instance().getLeaseType()
.includes(CommandOptions::LeaseType::PREFIX_ONLY)) {
pkt6->addOption(Option::factory(Option::V6, D6O_IA_PD));
}
......
......@@ -52,6 +52,33 @@ TEST(LeaseTypeTest, set) {
EXPECT_TRUE(lease_type.is(CommandOptions::LeaseType::PREFIX_ONLY));
}
TEST(LeaseTypeTest, includes) {
CommandOptions::LeaseType
lease_type(CommandOptions::LeaseType::ADDRESS_ONLY);
ASSERT_TRUE(lease_type.is(CommandOptions::LeaseType::ADDRESS_ONLY));
EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::ADDRESS_ONLY));
EXPECT_FALSE(lease_type.includes(CommandOptions::LeaseType::PREFIX_ONLY));
EXPECT_FALSE(
lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
);
lease_type.set(CommandOptions::LeaseType::PREFIX_ONLY);
EXPECT_FALSE(lease_type.includes(CommandOptions::LeaseType::ADDRESS_ONLY));
EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::PREFIX_ONLY));
EXPECT_FALSE(
lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
);
lease_type.set(CommandOptions::LeaseType::ADDRESS_AND_PREFIX);
EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::ADDRESS_ONLY));
EXPECT_TRUE(lease_type.includes(CommandOptions::LeaseType::PREFIX_ONLY));
EXPECT_TRUE(
lease_type.includes(CommandOptions::LeaseType::ADDRESS_AND_PREFIX)
);
}
TEST(LeaseTypeTest, fromCommandLine) {
CommandOptions::LeaseType
lease_type(CommandOptions::LeaseType::ADDRESS_ONLY);
......
......@@ -524,7 +524,8 @@ public:
/* ASSERT_NO_THROW(tc.processReceivedPacket6(sock,
advertise_pkt6)); */
try {
tc.processReceivedPacket6(sock, advertise_pkt6);
tc.processReceivedPacket6(sock,
advertise_pkt6);
} catch (const Exception& ex) {
std::cout << ex.what() << std::endl;
}
......@@ -652,20 +653,24 @@ private:
/// \return instance of the packet.
boost::shared_ptr<Pkt6>
createAdvertisePkt6(uint32_t transid) const {
OptionPtr opt_ia;
boost::shared_ptr<Pkt6> advertise(new Pkt6(DHCPV6_ADVERTISE, transid));
// Add IA_NA if requested by the client.
if (CommandOptions::instance().getLeaseType()
.includes(CommandOptions::LeaseType::ADDRESS_ONLY)) {
OptionPtr opt_ia_na = Option::factory(Option::V6, D6O_IA_NA);
advertise->addOption(opt_ia_na);
}
// Add IA_PD if requested by the client.
if (CommandOptions::instance().getLeaseType()
.is(CommandOptions::LeaseType::ADDRESS_ONLY)) {
opt_ia = Option::factory(Option::V6, D6O_IA_NA);
} else {
opt_ia = Option::factory(Option::V6, D6O_IA_PD);
.includes(CommandOptions::LeaseType::PREFIX_ONLY)) {
OptionPtr opt_ia_pd = Option::factory(Option::V6, D6O_IA_PD);
advertise->addOption(opt_ia_pd);
}
OptionPtr opt_serverid(new Option(Option::V6, D6O_SERVERID));
NakedTestControl tc;
uint8_t randomized = 0;
std::vector<uint8_t> duid(tc.generateDuid(randomized));
OptionPtr opt_clientid(Option::factory(Option::V6, D6O_CLIENTID, duid));
boost::shared_ptr<Pkt6> advertise(new Pkt6(DHCPV6_ADVERTISE, transid));
advertise->addOption(opt_ia);
advertise->addOption(opt_serverid);
advertise->addOption(opt_clientid);
advertise->updateTimestamp();
......@@ -1041,6 +1046,32 @@ TEST_F(TestControlTest, Packet6ExchangePrefixDelegation) {
EXPECT_EQ(10, iterations_performed);
}
TEST_F(TestControlTest, Packet6ExchangeAddressAndPrefix) {
// Get the local loopback interface to open socket on
// it and test packets exchanges. We don't want to fail
// the test if interface is not available.
std::string loopback_iface(getLocalLoopback());
if (loopback_iface.empty()) {
std::cout << "Unable to find the loopback interface. Skip test."
<< std::endl;
return;
}
const int iterations_num = 100;
// Set number of iterations to 10.
processCmdLine("perfdhcp -l " + loopback_iface
+ " -e address-and-prefix"
+ " -6 -r 100 -n 10 -R 20 -L 10547 ::1");
int iterations_performed = 0;
// Set number of received packets equal to number of iterations.
// This simulates no packet drops.
bool use_templates = false;
testPkt6Exchange(iterations_num, iterations_num, use_templates,
iterations_performed);
// Actual number of iterations should be 10.
EXPECT_EQ(10, iterations_performed);
}
TEST_F(TestControlTest, PacketTemplates) {
std::vector<uint8_t> template1(256);
std::string file1("test1.hex");
......
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