StatsMgr::instance().removeAll();
}
+ /// @brief Perform DORA exchange and checks the result
+ ///
+ /// This convenience method conducts DORA exchange with client
+ /// packets using hint values specified by third parameter.
+ /// The response is expected to be either ACK (ack = true) or
+ /// NAK (ack = false). The received address is checked against
+ /// exp_addr
+ ///
+ /// @param client client to perform the DORA exchange
+ /// @param exp_addr expected address (in yiaddr field)
+ /// @param hint the address the client is supposed to sent
+ /// (empty string means send 0.0.0.0)
+ /// @param ack expected response (true = ACK, false = NAK)
+ void
+ doDORA(Dhcp4Client& client, std::string exp_addr, std::string hint = "",
+ bool ack = true) {
+
+ if (hint.empty()) {
+ ASSERT_NO_THROW(client.doDORA());
+ } else {
+ boost::shared_ptr<IOAddress> addr(new IOAddress(hint));
+ ASSERT_NO_THROW(client.doDORA(addr));
+ }
+ Pkt4Ptr resp = client.getContext().response_;
+ ASSERT_TRUE(resp);
+ EXPECT_EQ((ack ? DHCPACK : DHCPNAK), resp->getType());
+ if (ack) {
+ EXPECT_EQ(exp_addr, resp->getYiaddr().toText());
+ } else {
+ EXPECT_EQ("0.0.0.0", resp->getYiaddr().toText());
+ }
+ }
+
+ /// @brief Perform Discover/Offer exchange and checks the result
+ ///
+ /// This convenience method conducts Discover/Offer exchange with client
+ /// packets using hint values specified by third parameter.
+ /// The response is expected to be either ACK (ack = true) or
+ /// NAK (ack = false). The received address is checked against
+ /// exp_addr
+ ///
+ /// @param client client to perform the DORA exchange
+ /// @param exp_addr expected address (in yiaddr field)
+ /// @param hint the address the client is supposed to sent
+ /// (empty string means send 0.0.0.0)
+ /// @param ack expected response (true = ACK, false = NAK)
+ void
+ doDiscover(Dhcp4Client& client, std::string exp_addr, std::string hint,
+ bool ack = true) {
+
+ if (hint.empty()) {
+ ASSERT_NO_THROW(client.doDiscover());
+ } else {
+ boost::shared_ptr<IOAddress> addr(new IOAddress(hint));
+ ASSERT_NO_THROW(client.doDiscover(addr));
+ }
+ Pkt4Ptr resp = client.getContext().response_;
+ ASSERT_TRUE(resp);
+ EXPECT_EQ((ack ? DHCPOFFER : DHCPNAK), resp->getType());
+ if (ack) {
+ EXPECT_EQ(exp_addr, resp->getYiaddr().toText());
+ } else {
+ EXPECT_EQ("0.0.0.0", resp->getYiaddr().toText());
+ }
+ }
+
+ /// @brief Perform Request/Reply exchange and checks the result
+ ///
+ /// This convenience method conducts Request/Reply exchange with client
+ /// packets using hint values specified by a parameter. The response is
+ /// expected to be either ACK if exp_addr has a non-empty length,
+ /// or NAK when exp_addr context is empty.
+ ///
+ /// @param client client to perform the DORA exchange
+ /// @param exp_addr expected address (in yiaddr field)
+ void
+ doRequest(Dhcp4Client& client, std::string exp_addr) {
+ ASSERT_NO_THROW(client.doRequest());
+ Pkt4Ptr resp = client.getContext().response_;
+ ASSERT_TRUE(resp);
+ if (exp_addr.empty()) {
+ EXPECT_EQ(DHCPNAK, resp->getType());
+ EXPECT_EQ("0.0.0.0", resp->getYiaddr().toText());
+ } else {
+ EXPECT_EQ(DHCPACK, resp->getType());
+ EXPECT_EQ(exp_addr, resp->getYiaddr().toText());
+ }
+ }
+
/// @brief Destructor.
virtual ~Dhcpv4SharedNetworkTest() {
StatsMgr::instance().removeAll();
configure(NETWORKS_CONFIG[0], *client1.getServer());
// Client #1 requests an address in first subnet within a shared network.
- ASSERT_NO_THROW(client1.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.63"))));
- Pkt4Ptr resp1 = client1.getContext().response_;
- ASSERT_TRUE(resp1);
- EXPECT_EQ(DHCPACK, resp1->getType());
- EXPECT_EQ("192.0.2.63", resp1->getYiaddr().toText());
+ // We'll send a hint of 192.0.2.63 and expect to get it.
+ doDORA(client1, "192.0.2.63", "192.0.2.63");
// Client #2 The second client will request a lease and should be assigned
// an address from the second subnet.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setIfaceName("eth1");
- ASSERT_NO_THROW(client2.doDORA());
- Pkt4Ptr resp2 = client2.getContext().response_;
- ASSERT_TRUE(resp2);
- EXPECT_EQ(DHCPACK, resp2->getType());
- EXPECT_EQ("10.0.0.16", resp2->getYiaddr().toText());
+ doDORA(client2, "10.0.0.16");
// Client #3. It sends DHCPDISCOVER which should be dropped by the server because
// the server has no more addresses to assign.
// Client #3 should be assigned an address if subnet 3 is selected for this client.
client3.setIfaceName("eth0");
- ASSERT_NO_THROW(client3.doDORA());
- resp3 = client3.getContext().response_;
- ASSERT_TRUE(resp3);
- EXPECT_EQ(DHCPACK, resp3->getType());
- EXPECT_EQ("192.0.2.65", resp3->getYiaddr().toText());
+ doDORA(client3, "192.0.2.65");
// Client #1 should be able to renew its address.
client1.setState(Dhcp4Client::RENEWING);
- ASSERT_NO_THROW(client1.doRequest());
- resp1 = client1.getContext().response_;
- ASSERT_TRUE(resp1);
- EXPECT_EQ(DHCPACK, resp1->getType());
- EXPECT_EQ("192.0.2.63", resp1->getYiaddr().toText());
+ doRequest(client1, "192.0.2.63");
// Client #2 should be able to renew its address.
client2.setState(Dhcp4Client::RENEWING);
- ASSERT_NO_THROW(client2.doRequest());
- resp2 = client2.getContext().response_;
- ASSERT_TRUE(resp2);
- EXPECT_EQ(DHCPACK, resp2->getType());
- EXPECT_EQ("10.0.0.16", resp2->getYiaddr().toText());
+ doRequest(client2, "10.0.0.16");
}
// Shared network is selected based on giaddr value.
configure(NETWORKS_CONFIG[1], *client1.getServer());
// Client #1 should be assigned an address from shared network.
- ASSERT_NO_THROW(client1.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.63"))));
- Pkt4Ptr resp1 = client1.getContext().response_;
- ASSERT_TRUE(resp1);
- EXPECT_EQ(DHCPACK, resp1->getType());
- EXPECT_EQ("192.0.2.63", resp1->getYiaddr().toText());
+ doDORA(client1, "192.0.2.63", "192.0.2.63");
// Create client #2. This is a relayed client which is using relay
// address matching subnet outside of the shared network.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.useRelay(true, IOAddress("192.1.2.3"), IOAddress("10.0.0.3"));
- ASSERT_NO_THROW(client2.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.63"))));
- Pkt4Ptr resp2 = client2.getContext().response_;
- ASSERT_TRUE(resp2);
- EXPECT_EQ(DHCPACK, resp2->getType());
- EXPECT_EQ("192.0.2.65", resp2->getYiaddr().toText());
+ doDORA(client2, "192.0.2.65", "192.0.2.63");
}
// Providing a hint for any address belonging to a shared network.
// Provide a hint to an existing address within first subnet. This address
// should be offered out of this subnet.
- ASSERT_NO_THROW(client.doDiscover(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.63"))));
- Pkt4Ptr resp = client.getContext().response_;
- ASSERT_TRUE(resp);
- EXPECT_EQ(DHCPOFFER, resp->getType());
- EXPECT_EQ("192.0.2.63", resp->getYiaddr().toText());
+ doDiscover(client, "192.0.2.63", "192.0.2.63");
// Similarly, we should be offered an address from another subnet within
// the same shared network when we ask for it.
- ASSERT_NO_THROW(client.doDiscover(boost::shared_ptr<IOAddress>(new IOAddress("10.0.0.16"))));
- resp = client.getContext().response_;
- ASSERT_TRUE(resp);
- EXPECT_EQ(DHCPOFFER, resp->getType());
- EXPECT_EQ("10.0.0.16", resp->getYiaddr().toText());
+ doDiscover(client, "10.0.0.16", "10.0.0.16");
// Asking for an address that is not in address pool should result in getting
// an address from one of the subnets, but generally hard to tell from which one.
ASSERT_NO_THROW(client.doDiscover(boost::shared_ptr<IOAddress>(new IOAddress("10.0.0.23"))));
- resp = client.getContext().response_;
+ Pkt4Ptr resp = client.getContext().response_;
ASSERT_TRUE(resp);
// We expect one of the two addresses available in this shared network.
// Client #1 requests an address in the restricted subnet but can't be assigned
// this address because the client doesn't belong to a certain class.
- ASSERT_NO_THROW(client1.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.63"))));
- Pkt4Ptr resp1 = client1.getContext().response_;
- ASSERT_TRUE(resp1);
- EXPECT_EQ(DHCPACK, resp1->getType());
- EXPECT_EQ("10.0.0.16", resp1->getYiaddr().toText());
+ doDORA(client1, "10.0.0.16", "192.0.2.63");
// Release the lease that the client has got, because we'll need this address
// further in the test.
client1.addExtraOption(option93);
// This time, the allocation of the address provided as hint should be successful.
- ASSERT_NO_THROW(client1.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.63"))));
- resp1 = client1.getContext().response_;
- ASSERT_TRUE(resp1);
- EXPECT_EQ(DHCPACK, resp1->getType());
- EXPECT_EQ("192.0.2.63", resp1->getYiaddr().toText());
+ doDORA(client1, "192.0.2.63", "192.0.2.63");
// Client 2 should be assigned an address from the unrestricted subnet.
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.useRelay(true, IOAddress("192.3.5.6"));
client2.setIfaceName("eth1");
- ASSERT_NO_THROW(client2.doDORA());
- Pkt4Ptr resp2 = client2.getContext().response_;
- ASSERT_TRUE(resp2);
- EXPECT_EQ(DHCPACK, resp2->getType());
- EXPECT_EQ("10.0.0.16", resp2->getYiaddr().toText());
+ doDORA(client2, "10.0.0.16");
// Now, let's reconfigure the server to also apply restrictions on the
// subnet to which client2 now belongs.
// The client should be refused to renew the lease because it doesn't belong
// to "b-devices" class.
client2.setState(Dhcp4Client::RENEWING);
- ASSERT_NO_THROW(client2.doRequest());
- resp2 = client2.getContext().response_;
- ASSERT_TRUE(resp2);
- EXPECT_EQ(DHCPNAK, resp2->getType());
+ doRequest(client2, "");
// If we add option93 with a value matching this class, the lease should
// get renewed.
OptionPtr option93_bis(new OptionUint16(Option::V4, 93, 0x0002));
client2.addExtraOption(option93_bis);
-
- ASSERT_NO_THROW(client2.doRequest());
- resp2 = client2.getContext().response_;
- ASSERT_TRUE(resp2);
- EXPECT_EQ(DHCPACK, resp2->getType());
- EXPECT_EQ("10.0.0.16", resp2->getYiaddr().toText());
}
// IPv4 address reservation exists in one of the subnets within
configure(NETWORKS_CONFIG[4], *client1.getServer());
// Client #1 should get his reserved address from the second subnet.
- ASSERT_NO_THROW(client1.doDORA(boost::shared_ptr<IOAddress>(new IOAddress("192.0.2.28"))));
- Pkt4Ptr resp1 = client1.getContext().response_;
- ASSERT_TRUE(resp1);
- EXPECT_EQ(DHCPACK, resp1->getType());
- EXPECT_EQ("10.0.0.29", resp1->getYiaddr().toText());
+ doDORA(client1, "10.0.0.29", "192.0.2.28");
// Create client #2
Dhcp4Client client2(client1.getServer(), Dhcp4Client::SELECTING);
client2.setHWAddress("aa:bb:cc:dd:ee:ff");
// Client #2 should get its reserved address from the first subnet.
- ASSERT_NO_THROW(client2.doDORA());
- Pkt4Ptr resp2 = client2.getContext().response_;
- ASSERT_TRUE(resp2);
- EXPECT_EQ(DHCPACK, resp2->getType());
- EXPECT_EQ("192.0.2.28", resp2->getYiaddr().toText());
+ doDORA(client2, "192.0.2.28");
// Reconfigure the server. Now, the first client gets second client's
// reservation and vice versa.
// The first client is trying to renew the lease and should get a DHCPNAK.
client1.setState(Dhcp4Client::RENEWING);
- ASSERT_NO_THROW(client1.doRequest());
- resp1 = client1.getContext().response_;
- ASSERT_TRUE(resp1);
- EXPECT_EQ(DHCPNAK, resp1->getType());
+ doRequest(client1, "");
// Similarly, the second client is trying to renew the lease and should
// get a DHCPNAK.
client2.setState(Dhcp4Client::RENEWING);
- ASSERT_NO_THROW(client2.doRequest());
- resp2 = client2.getContext().response_;
- ASSERT_TRUE(resp2);
- EXPECT_EQ(DHCPNAK, resp2->getType());
+ doRequest(client2, "");
// But the client should get a lease, if it does 4-way exchange. However, it
// must not get any of the reserved addresses because one of them is reserved
// for another client and for another one there is a valid lease.
client1.setState(Dhcp4Client::SELECTING);
ASSERT_NO_THROW(client1.doDORA());
- resp1 = client1.getContext().response_;
+ Pkt4Ptr resp1 = client1.getContext().response_;
ASSERT_TRUE(resp1);
EXPECT_EQ(DHCPACK, resp1->getType());
EXPECT_NE("10.0.0.29", resp1->getYiaddr().toText());
// Client #2 is now doing 4-way exchange and should get its newly reserved
// address, released by the 4-way transaction of client 1.
client2.setState(Dhcp4Client::SELECTING);
- ASSERT_NO_THROW(client2.doDORA());
- resp2 = client2.getContext().response_;
- ASSERT_TRUE(resp2);
- EXPECT_EQ(DHCPACK, resp2->getType());
- EXPECT_EQ("10.0.0.29", resp2->getYiaddr().toText());
+ doDORA(client2, "10.0.0.29");
// Same for client #1.
client1.setState(Dhcp4Client::SELECTING);
- ASSERT_NO_THROW(client1.doDORA());
- resp1 = client1.getContext().response_;
- ASSERT_TRUE(resp1);
- EXPECT_EQ(DHCPACK, resp1->getType());
- EXPECT_EQ("192.0.2.28", resp1->getYiaddr().toText());
+ doDORA(client1, "192.0.2.28");
}
// Reserved address can't be assigned as long as access to a subnet is