/// respond to requests from unknown clients.
///
const char* DORA_CONFIGS[] = {
-// Configuration 0
+ // Configuration 0
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
" } ]"
"}",
-// Configuration 1
+ // Configuration 1
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
" } ]"
"}",
-// Configuration 2
+ // Configuration 2
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"} ]"
"}",
-// Configuration 3
+ // Configuration 3
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
" } ]"
"}",
-// Configuration 4
+ // Configuration 4
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"} ]"
"}",
-// Configuration 6
+ // Configuration 6
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"} ]"
"}",
-// Configuration 7
+ // Configuration 7
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"]"
"}",
-// Configuration 8
+ // Configuration 8
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
" } ]"
"}",
-// Configuration 9
+ // Configuration 9
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
" } ]"
"}",
-// Configuration 10
+ // Configuration 10
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
" } ]"
"}",
-// Configuration 11
+ // Configuration 11
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"} ]"
"}",
-// Configuration 12
+ // Configuration 12
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"} ]"
"}",
-// Configuration 13
+ // Configuration 13
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"} ]"
"}",
-// Configuration 14
+ // Configuration 14
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
"} ]"
"}",
-// Configuration 15
+ // Configuration 15
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
" } ]"
"}",
-// Configuration 16
+ // Configuration 16
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
" } ]"
"}",
-// Configuration 17
+ // Configuration 17
"{ \"interfaces-config\": {"
" \"interfaces\": [ \"*\" ]"
"},"
/// @c DORA_CONFIGS array.
void testMultiStageBoot(const unsigned int config_index);
+ /// @brief This test verifies that the client in the SELECTING state can get
+ /// an address when it doesn't request any specific address in the
+ /// DHCPDISCOVER message.
+ void selectingDoNotRequestAddress();
+
+ /// @brief This test verifies that multiple clients may use the DHCPv4
+ /// server and obtain unique leases.
+ void selectingMultipleClients();
+
+ /// @brief This test verifies that the client in a SELECTING state can
+ /// request a specific address and that this address will be assigned when
+ /// available. It also tests that if the client requests an address which is
+ /// in use the client will get a different address.
+ void selectingRequestAddress();
+
+ /// @brief This test verifies that the client will get the address that it
+ /// has been allocated when the client requests a different address.
+ void selectingRequestNonMatchingAddress();
+
+ /// @brief Test that the client in the INIT-REBOOT state can request the IP
+ /// address it has and the address is returned. Also, check that if the
+ /// client requests invalid address the server sends a DHCPNAK.
+ void initRebootRequest();
+
+ /// @brief Test that the client in the INIT-REBOOT state can request the IP
+ /// address it has and the address is returned. Also, check that if the
+ /// client is unknown the server sends a DHCPNAK.
+ void authoritative();
+
+ /// @brief Test that the client in the INIT-REBOOT state can request the IP
+ /// address it has and the address is returned. Also, check that if the
+ /// client is unknown the request is dropped.
+ void notAuthoritative();
+
+ /// @brief Check that the ciaddr returned by the server is correct for
+ /// DHCPOFFER and DHCPNAK according to RFC2131, section 4.3.1.
+ void ciaddr();
+
+ /// @brief This test checks the server behavior in the following situation:
+ /// - Client A identifies itself to the server using client identifier
+ /// and the hardware address and requests allocation of the new lease.
+ /// - Server allocates the lease to the client.
+ /// - Client B has the same hardware address but is using a different
+ /// client identifier then Client A.
+ /// - Client B sends DHCPDISCOVER.
+ /// - Server should determine that the client B is not client A, because
+ /// it is using a different client identifier, even though they use the
+ /// same HW address. As a consequence, the server should offer a
+ /// different address to the client B.
+ /// - The client B performs the 4-way exchange again and the server
+ /// allocates a new address to the client, which should be different
+ /// than the address used by the client A.
+ /// - Client B is in the renewing state and it successfully renews its
+ /// address.
+ /// - Client A also renews its address successfully.
+ void twoAllocationsOverlap();
+
+ /// @brief This is a simple test for the host reservation. It creates a
+ /// reservation for an address for a single client, identified by the HW
+ /// address. The test verifies that the client using this HW address will
+ /// obtain a lease for the reserved address. It also checks that the client
+ /// using a different HW address will obtain an address from the dynamic
+ /// pool.
+ void reservation();
+
+ /// @brief This test checks that it is possible to make a reservation by
+ /// DUID carried in the Client Identifier option.
+ void reservationByDUID();
+
+ /// @brief This test checks that it is possible to make a reservation by
+ /// circuit-id inserted by the relay agent.
+ void reservationByCircuitId();
+
+ /// @brief This test checks that it is possible to make a reservation by
+ /// client-id.
+ void reservationByClientId();
+
+ /// @brief This test verifies that order in which host identifiers are used
+ /// to retrieve host reservations can be controlled.
+ void hostIdentifiersOrder();
+
+ /// @brief This test checks that setting the match-client-id value to false
+ /// causes the server to ignore changing client identifier when the client
+ /// is using consistent HW address.
+ void ignoreChangingClientId();
+
+ /// @brief This test checks that the match-client-id parameter doesn't have
+ /// effect on the lease lookup using the HW address.
+ void changingHWAddress();
+
+ /// @brief This test verifies that the server assigns reserved values for
+ /// the siaddr, sname and file fields carried within DHCPv4 message.
+ void messageFieldsReservations();
+
+ /// @brief This test checks the following scenario:
+ /// 1. Client A performs 4-way exchange and obtains a lease from the dynamic
+ /// pool.
+ /// 2. Reservation is created for the client A using an address out of the
+ /// dynamic pool.
+ /// 3. Client A renews the lease.
+ /// 4. Server responds with DHCPNAK to indicate that the client should stop
+ /// using an address for which it has a lease. Server doesn't want to
+ /// renew an address for which the client doesn't have a reservation,
+ /// while it has a reservation for a different address.
+ /// 5. Client A receives a DHCPNAK and returns to the DHCP server discovery.
+ /// 6. Client A performs a 4-way exchange with a server and the server
+ /// allocates a reserved address to the Client A.
+ /// 7. Client A renews the allocated address and the server returns a
+ /// DHCPACK.
+ /// 8. Reservation for the Client A is removed.
+ /// 9. Client A renews the (previously reserved) lease and the server
+ /// returns DHCPNAK because the address in use is neither reserved nor
+ /// belongs to the dynamic pool.
+ /// 10. Client A returns to the DHCP server discovery.
+ /// 11. Client A uses 4-way exchange to obtain a lease from the dynamic
+ /// pool.
+ /// 12. The new address that the Client A is using is reserved for Client B.
+ /// Client A still holds this address.
+ /// 13. Client B uses 4-way exchange to obtain a new lease.
+ /// 14. The server determines that the Client B has a reservation for the
+ /// address which is in use by Client A and offers an address different
+ /// than reserved.
+ /// 15. Client B requests the allocation of the offered address and the
+ /// server allocates this address.
+ /// 16. Client A renews the lease.
+ /// 17. The server determines that the address that Client A is using is
+ /// reserved for Client B. The server returns DHCPNAK to the Client A.
+ /// 18. Client B uses 4-way exchange to obtain the reserved lease but the
+ /// lease for the Client A hasn't been removed yet. Client B is assigned
+ /// the same address it has been using.
+ /// 19. Client A uses 4-way exchange to allocate a new lease.
+ /// 20. The server allocates a new lease from the dynamic pool but it avoids
+ /// allocating the address reserved for the Client B.
+ /// 21. Client B uses 4-way exchange to obtain a new lease.
+ /// 22. The server finally allocates a reserved address to the Client B.
+ void reservationsWithConflicts();
+
+ /// @brief This test verifies that the allocation engine ignores
+ /// reservations when reservations flags are set to "disabled".
+ void reservationModeDisabled();
+
+ /// @brief This test verifies that allocation engine assigns a reserved
+ /// address to the client which doesn't own this reservation. We want to
+ /// avoid such cases in the real deployments, but this is just a test that
+ /// the allocation engine skips checking if the reservation exists when it
+ /// allocates an address. In the real deployment the reservation simply
+ /// wouldn't exist.
+ void reservationIgnoredInDisabledMode();
+
+ /// @brief This test verifies that in pool reservations are ignored when the
+ /// reservations-out-of-pool flag is set to true.
+ void reservationModeOutOfPool();
+
+ /// @brief This test verifies that the in-pool reservation can be assigned
+ /// to a client not owning this reservation when the
+ /// reservations-out-of-pool flag is set to true.
+ void reservationIgnoredInOutOfPoolMode();
+
+ /// @brief This test verifies that after a client completes its DORA
+ /// exchange, appropriate statistics are updated.
+ void statisticsDORA();
+
+ /// @brief This test verifies that after a client completes an exchange that
+ /// result in NAK, appropriate statistics are updated.
+ void statisticsNAK();
+
+ /// @brief This test verifies that custom server identifier can be specified
+ /// for a subnet.
+ void customServerIdentifier();
+
+ /// @brief This test verifies that reserved lease is not assigned to a
+ /// client which identifier doesn't match the identifier in the reservation.
+ void changingCircuitId();
+
+ /// @brief Verifies that extended info is stored on the lease when
+ /// store-extended-info is enabled.
+ void storeExtendedInfoEnabled();
+
+ /// @brief Verifies that extended info is not stored on the lease when
+ /// store-extended-info is disabled.
+ void storeExtendedInfoDisabled();
+
/// @brief Interface Manager's fake configuration control.
IfaceMgrTestConfig iface_mgr_test_config_;
-
};
-/// This test verifies that the client in the SELECTING state can get
-/// an address when it doesn't request any specific address in the
-/// DHCPDISCOVER message.
-TEST_F(DORATest, selectingDoNotRequestAddress) {
+void
+DORATest::selectingDoNotRequestAddress() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[0], *client.getServer());
ASSERT_NE(client.config_.lease_.addr_.toText(), "0.0.0.0");
}
-/// This test verifies that multiple clients may use the DHCPv4 server
-/// and obtain unique leases.
-TEST_F(DORATest, selectingMultipleClients) {
+TEST_F(DORATest, selectingDoNotRequestAddress) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ selectingDoNotRequestAddress();
+}
+
+TEST_F(DORATest, selectingDoNotRequestAddressMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ selectingDoNotRequestAddress();
+}
+
+void
+DORATest::selectingMultipleClients() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[0], *client.getServer());
EXPECT_NE(lease1.addr_, lease3.addr_);
}
-// This test verifies that the client in a SELECTING state can request
-// a specific address and that this address will be assigned when
-// available. It also tests that if the client requests an address which
-// is in use the client will get a different address.
-TEST_F(DORATest, selectingRequestAddress) {
+TEST_F(DORATest, selectingMultipleClients) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ selectingMultipleClients();
+}
+
+TEST_F(DORATest, selectingMultipleClientsMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ selectingMultipleClients();
+}
+
+void
+DORATest::selectingRequestAddress() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[0], *client.getServer());
EXPECT_NE(client.config_.lease_.addr_.toText(), "10.0.0.50");
}
-// This test verifies that the client will get the address that it has
-// been allocated when the client requests a different address.
-TEST_F(DORATest, selectingRequestNonMatchingAddress) {
+TEST_F(DORATest, selectingRequestAddress) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ selectingRequestAddress();
+}
+
+TEST_F(DORATest, selectingRequestAddressMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ selectingRequestAddress();
+}
+
+void
+DORATest::selectingRequestNonMatchingAddress() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[0], *client.getServer());
EXPECT_EQ("10.0.0.50", client.config_.lease_.addr_.toText());
}
-// Test that the client in the INIT-REBOOT state can request the IP
-// address it has and the address is returned. Also, check that if
-// if the client requests invalid address the server sends a DHCPNAK.
-TEST_F(DORATest, initRebootRequest) {
+TEST_F(DORATest, selectingRequestNonMatchingAddress) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ selectingRequestNonMatchingAddress();
+}
+
+TEST_F(DORATest, selectingRequestNonMatchingAddressMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ selectingRequestNonMatchingAddress();
+}
+
+void
+DORATest::initRebootRequest() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[0], *client.getServer());
ASSERT_EQ("10.0.0.50", client.config_.lease_.addr_.toText());
}
-// Test that the client in the INIT-REBOOT state can request the IP
-// address it has and the address is returned. Also, check that if
-// if the client is unknown the server sends a DHCPNAK.
-TEST_F(DORATest, authoritative) {
+TEST_F(DORATest, initRebootRequest) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ initRebootRequest();
+}
+
+TEST_F(DORATest, initRebootRequestMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ initRebootRequest();
+}
+
+void
+DORATest::authoritative() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[15], *client.getServer());
ASSERT_EQ("10.0.0.50", client.config_.lease_.addr_.toText());
}
-// Test that the client in the INIT-REBOOT state can request the IP
-// address it has and the address is returned. Also, check that if
-// if the client is unknown the request is dropped.
-TEST_F(DORATest, notAuthoritative) {
+TEST_F(DORATest, authoritative) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ authoritative();
+}
+
+TEST_F(DORATest, authoritativeMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ authoritative();
+}
+
+void
+DORATest::notAuthoritative() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[16], *client.getServer());
ASSERT_EQ("10.0.0.50", client.config_.lease_.addr_.toText());
}
-// Check that the ciaddr returned by the server is correct for DHCPOFFER and
-// DHCPNAK according to RFC2131, section 4.3.1.
-TEST_F(DORATest, ciaddr) {
+TEST_F(DORATest, notAuthoritative) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ notAuthoritative();
+}
+
+TEST_F(DORATest, notAuthoritativeMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ notAuthoritative();
+}
+
+void
+DORATest::ciaddr() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[0], *client.getServer());
EXPECT_EQ("0.0.0.0", resp->getCiaddr().toText());
}
+TEST_F(DORATest, ciaddr) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ ciaddr();
+}
+
+TEST_F(DORATest, ciaddrMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ ciaddr();
+}
+
void
DORATest::oneAllocationOverlapTest(const std::string& clientid_a,
const std::string& clientid_b) {
ASSERT_EQ(yiaddr, client.config_.lease_.addr_);
}
-// This test checks the server behavior in the following situation:
-// - Client A identifies itself to the server using client identifier
-// and the hardware address and requests allocation of the new lease.
-// - Server allocates the lease to the client.
-// - Client B has the same hardware address but is using a different
-// client identifier then Client A.
-// - Client B sends DHCPDISCOVER.
-// - Server should determine that the client B is not client A, because
-// it is using a different client identifier, even though they use the
-// same HW address. As a consequence, the server should offer a
-// different address to the client B.
-// - The client B performs the 4-way exchange again and the server
-// allocates a new address to the client, which should be different
-// than the address used by the client A.
-// - Client B is in the renewing state and it successfully renews its
-// address.
-// - Client A also renews its address successfully.
-TEST_F(DORATest, twoAllocationsOverlap) {
+void
+DORATest::twoAllocationsOverlap() {
// Allocate a lease by client A using the 4-way exchange.
Dhcp4Client client_a(Dhcp4Client::SELECTING);
client_a.includeClientId("12:34");
ASSERT_NE(client_a.config_.lease_.addr_, client_b.config_.lease_.addr_);
}
+TEST_F(DORATest, twoAllocationsOverlap) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ twoAllocationsOverlap();
+}
+
+TEST_F(DORATest, twoAllocationsOverlapMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ twoAllocationsOverlap();
+}
+
// This test checks the server behavior in the following situation:
// - Client A identifies itself to the server using the hardware address
// and client identifier.
// same reason.
// - Client A renews its address successfully.
TEST_F(DORATest, oneAllocationOverlap1) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ oneAllocationOverlapTest("12:34", "");
+}
+
+// This test checks the server behavior in the following situation:
+// - Client A identifies itself to the server using the hardware address
+// and client identifier.
+// - Client A performs the 4-way exchange and obtains a lease from the server.
+// - Client B uses the same HW address as the client A, but it doesn't use
+// the client identifier.
+// - Client B sends the DHCPDISCOVER to the server.
+// The server determines that there is a lease for the client A using the
+// same HW address as the client B. Server discards the client's message and
+// doesn't offer the lease for the client B to prevent allocation of the
+// lease without a unique identifier.
+// - The client sends the DHCPREQUEST and the server sends the DHCPNAK for the
+// same reason.
+// - Client A renews its address successfully.
+TEST_F(DORATest, oneAllocationOverlap1MultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
oneAllocationOverlapTest("12:34", "");
}
// uses no client identifier, and the client B uses the HW address and the
// client identifier. The server behaves as previously.
TEST_F(DORATest, oneAllocationOverlap2) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
oneAllocationOverlapTest("", "12:34");
}
-// This is a simple test for the host reservation. It creates a reservation
-// for an address for a single client, identified by the HW address. The
-// test verifies that the client using this HW address will obtain a
-// lease for the reserved address. It also checks that the client using
-// a different HW address will obtain an address from the dynamic pool.
-TEST_F(DORATest, reservation) {
+// This test is similar to oneAllocationOverlap2 but this time the client A
+// uses no client identifier, and the client B uses the HW address and the
+// client identifier. The server behaves as previously.
+TEST_F(DORATest, oneAllocationOverlap2MultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ oneAllocationOverlapTest("", "12:34");
+}
+
+void
+DORATest::reservation() {
// Client A is a one which will have a reservation.
Dhcp4Client clientA(Dhcp4Client::SELECTING);
// Set explicit HW address so as it matches the reservation in the
ASSERT_TRUE(subnet->inPool(Lease::TYPE_V4, clientB.config_.lease_.addr_));
}
-// This test checks that it is possible to make a reservation by
-// DUID carried in the Client Identifier option.
-TEST_F(DORATest, reservationByDUID) {
+TEST_F(DORATest, reservation) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ reservation();
+}
+
+TEST_F(DORATest, reservationMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ reservation();
+}
+
+void
+DORATest:: reservationByDUID() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Use relay agent.
client.useRelay(true, IOAddress("10.0.0.1"), IOAddress("10.0.0.2"));
ASSERT_EQ("10.0.0.8", client.config_.lease_.addr_.toText());
}
-// This test checks that it is possible to make a reservation by
-// circuit-id inserted by the relay agent.
-TEST_F(DORATest, reservationByCircuitId) {
+TEST_F(DORATest, reservationByDUID) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ reservationByDUID();
+}
+
+TEST_F(DORATest, reservationByDUIDMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ reservationByDUID();
+}
+
+void
+DORATest::reservationByCircuitId() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Use relay agent so as the circuit-id can be inserted.
client.useRelay(true, IOAddress("10.0.0.1"), IOAddress("10.0.0.2"));
ASSERT_EQ("10.0.0.9", client.config_.lease_.addr_.toText());
}
-// This test checks that it is possible to make a reservation by
-// client-id.
-TEST_F(DORATest, reservationByClientId) {
+TEST_F(DORATest, reservationByCircuitId) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ reservationByCircuitId();
+}
+
+TEST_F(DORATest, reservationByCircuitIdMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ reservationByCircuitId();
+}
+
+void
+DORATest::reservationByClientId() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Use relay agent to make sure that the desired subnet is
// selected for our client.
ASSERT_EQ("10.0.0.1", client.config_.lease_.addr_.toText());
}
-// This test verifies that order in which host identifiers are used to
-// retrieve host reservations can be controlled.
-TEST_F(DORATest, hostIdentifiersOrder) {
+TEST_F(DORATest, reservationByClientId) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ reservationByClientId();
+}
+
+TEST_F(DORATest, reservationByClientIdMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ reservationByClientId();
+}
+
+void
+DORATest::hostIdentifiersOrder() {
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setHWAddress("aa:bb:cc:dd:ee:ff");
// Use relay agent so as the circuit-id can be inserted.
ASSERT_EQ("10.0.0.1", client.config_.lease_.addr_.toText());
}
-// This test checks that setting the match-client-id value to false causes
-// the server to ignore changing client identifier when the client is
-// using consistent HW address.
-TEST_F(DORATest, ignoreChangingClientId) {
+TEST_F(DORATest, hostIdentifiersOrder) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ hostIdentifiersOrder();
+}
+
+TEST_F(DORATest, hostIdentifiersOrderMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ hostIdentifiersOrder();
+}
+
+void
+DORATest::ignoreChangingClientId() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[3], *client.getServer());
EXPECT_FALSE(client.config_.lease_.client_id_);
}
-// This test checks that the match-client-id parameter doesn't have
-// effect on the lease lookup using the HW address.
-TEST_F(DORATest, changingHWAddress) {
+TEST_F(DORATest, ignoreChangingClientId) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ ignoreChangingClientId();
+}
+
+TEST_F(DORATest, ignoreChangingClientIdMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ ignoreChangingClientId();
+}
+
+void
+DORATest::changingHWAddress() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[3], *client.getServer());
EXPECT_FALSE(client.config_.lease_.client_id_);
}
-// This test verifies that the server assigns reserved values for the
-// siaddr, sname and file fields carried within DHCPv4 message.
-TEST_F(DORATest, messageFieldsReservations) {
+TEST_F(DORATest, changingHWAddress) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ changingHWAddress();
+}
+
+TEST_F(DORATest, changingHWAddressMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ changingHWAddress();
+}
+
+void
+DORATest::messageFieldsReservations() {
// Client has a reservation.
Dhcp4Client client(Dhcp4Client::SELECTING);
// Set explicit HW address so as it matches the reservation in the
EXPECT_EQ("bootfile.efi", client.config_.boot_file_name_);
}
-// This test checks the following scenario:
-// 1. Client A performs 4-way exchange and obtains a lease from the dynamic pool.
-// 2. Reservation is created for the client A using an address out of the dynamic
-// pool.
-// 3. Client A renews the lease.
-// 4. Server responds with DHCPNAK to indicate that the client should stop using
-// an address for which it has a lease. Server doesn't want to renew an
-// address for which the client doesn't have a reservation, while it has
-// a reservation for a different address.
-// 5. Client A receives a DHCPNAK and returns to the DHCP server discovery.
-// 6. Client A performs a 4-way exchange with a server and the server allocates
-// a reserved address to the Client A.
-// 7. Client A renews the allocated address and the server returns a DHCPACK.
-// 8. Reservation for the Client A is removed.
-// 9. Client A renews the (previously reserved) lease and the server returns
-// DHCPNAK because the address in use is neither reserved nor belongs to
-// the dynamic pool.
-// 10. Client A returns to the DHCP server discovery.
-// 11. Client A uses 4-way exchange to obtain a lease from the dynamic pool.
-// 12. The new address that the Client A is using is reserved for Client B.
-// Client A still holds this address.
-// 13. Client B uses 4-way exchange to obtain a new lease.
-// 14. The server determines that the Client B has a reservation for the
-// address which is in use by Client A and offers an address different
-// than reserved.
-// 15. Client B requests the allocation of the offered address and the server
-// allocates this address.
-// 16. Client A renews the lease.
-// 17. The server determines that the address that Client A is using is reserved
-// for Client B. The server returns DHCPNAK to the Client A.
-// 18. Client B uses 4-way exchange to obtain the reserved lease but the lease
-// for the Client A hasn't been removed yet. Client B is assigned the same
-// address it has been using.
-// 19. Client A uses 4-way exchange to allocate a new lease.
-// 20. The server allocates a new lease from the dynamic pool but it avoids
-// allocating the address reserved for the Client B.
-// 21. Client B uses 4-way exchange to obtain a new lease.
-// 22. The server finally allocates a reserved address to the Client B.
-TEST_F(DORATest, reservationsWithConflicts) {
+TEST_F(DORATest, messageFieldsReservations) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ messageFieldsReservations();
+}
+
+TEST_F(DORATest, messageFieldsReservationsMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ messageFieldsReservations();
+}
+
+void
+DORATest::reservationsWithConflicts() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[0], *client.getServer());
ASSERT_EQ(in_pool_addr, clientB.config_.lease_.addr_);
}
-// This test verifies that the allocation engine ignores reservations when
-// reservations flags are set to "disabled".
-TEST_F(DORATest, reservationModeDisabled) {
+TEST_F(DORATest, reservationsWithConflicts) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ reservationsWithConflicts();
+}
+
+TEST_F(DORATest, reservationsWithConflictsMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ reservationsWithConflicts();
+}
+
+void
+DORATest::reservationModeDisabled() {
// Client has a reservation.
Dhcp4Client client(Dhcp4Client::SELECTING);
// Set explicit HW address so as it matches the reservation in the
ASSERT_EQ("10.0.0.65", client.config_.lease_.addr_.toText());
}
-// This test verifies that allocation engine assigns a reserved address to
-// the client which doesn't own this reservation. We want to avoid such
-// cases in the real deployments, but this is just a test that the allocation
-// engine skips checking if the reservation exists when it allocates an
-// address. In the real deployment the reservation simply wouldn't exist.
-TEST_F(DORATest, reservationIgnoredInDisabledMode) {
+TEST_F(DORATest, reservationModeDisabled) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ reservationModeDisabled();
+}
+
+TEST_F(DORATest, reservationModeDisabledMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ reservationModeDisabled();
+}
+
+void
+DORATest::reservationIgnoredInDisabledMode() {
// Client has a reservation.
Dhcp4Client client(Dhcp4Client::SELECTING);
// Set MAC address which doesn't match the reservation configured.
ASSERT_EQ("10.0.0.65", client.config_.lease_.addr_.toText());
}
-// This test verifies that in pool reservations are ignored when the
-// reservations-out-of-pool flag is set to true.
-TEST_F(DORATest, reservationModeOutOfPool) {
+TEST_F(DORATest, reservationIgnoredInDisabledMode) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ reservationIgnoredInDisabledMode();
+}
+
+TEST_F(DORATest, reservationIgnoredInDisabledModeMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ reservationIgnoredInDisabledMode();
+}
+
+void
+DORATest::reservationModeOutOfPool() {
// Create the first client for which we have a reservation out of the
// dynamic pool.
Dhcp4Client clientA(Dhcp4Client::SELECTING);
ASSERT_EQ("10.0.0.40", clientB.config_.lease_.addr_.toText());
}
-// This test verifies that the in-pool reservation can be assigned to a client
-// not owning this reservation when the reservations-out-of-pool flag is set to
-// true.
-TEST_F(DORATest, reservationIgnoredInOutOfPoolMode) {
+TEST_F(DORATest, reservationModeOutOfPool) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ reservationModeOutOfPool();
+}
+
+TEST_F(DORATest, reservationModeOutOfPoolMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ reservationModeOutOfPool();
+}
+
+void
+DORATest::reservationIgnoredInOutOfPoolMode() {
// Create the first client for which we have a reservation out of the
// dynamic pool.
Dhcp4Client client(Dhcp4Client::SELECTING);
ASSERT_EQ("10.0.0.65", client.config_.lease_.addr_.toText());
}
-/// This test verifies that after a client completes its DORA exchange,
-/// appropriate statistics are updated.
-TEST_F(DORATest, statisticsDORA) {
+TEST_F(DORATest, reservationIgnoredInOutOfPoolMode) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ reservationIgnoredInOutOfPoolMode();
+}
+
+TEST_F(DORATest, reservationIgnoredInOutOfPoolModeMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ reservationIgnoredInOutOfPoolMode();
+}
+
+void
+DORATest::statisticsDORA() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[0], *client.getServer());
EXPECT_EQ(5, pkt4_sent->getInteger().first);
}
-// This test verifies that after a client completes an exchange that result
-// in NAK, appropriate statistics are updated.
-TEST_F(DORATest, statisticsNAK) {
+TEST_F(DORATest, statisticsDORA) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ statisticsDORA();
+}
+
+TEST_F(DORATest, statisticsDORAMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ statisticsDORA();
+}
+
+void
+DORATest::statisticsNAK() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Configure DHCP server.
configure(DORA_CONFIGS[0], *client.getServer());
EXPECT_EQ(1, pkt4_sent->getInteger().first);
}
+TEST_F(DORATest, statisticsNAK) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ statisticsNAK();
+}
+
+TEST_F(DORATest, statisticsNAKMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ statisticsNAK();
+}
+
void
DORATest::testMultiStageBoot(const unsigned int config_index) {
Dhcp4Client client(Dhcp4Client::SELECTING);
ASSERT_NE(leased_address2, leased_address3);
}
-
// Test that the client using the same hardware address but multiple
// client identifiers will obtain multiple leases.
TEST_F(DORATest, multiStageBoot) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
// DORA_CONFIGS[0] to be used for server configuration.
testMultiStageBoot(0);
}
-// This test verifies that custom server identifier can be specified for
-// a subnet.
-TEST_F(DORATest, customServerIdentifier) {
+// Test that the client using the same hardware address but multiple
+// client identifiers will obtain multiple leases.
+TEST_F(DORATest, multiStageBootMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ // DORA_CONFIGS[0] to be used for server configuration.
+ testMultiStageBoot(0);
+}
+
+void
+DORATest::customServerIdentifier() {
Dhcp4Client client1(Dhcp4Client::SELECTING);
// Configure DHCP server.
ASSERT_NO_THROW(configure(DORA_CONFIGS[7], *client1.getServer()));
EXPECT_EQ("3.4.5.6", client3.config_.serverid_.toText());
}
-// This test verifies that reserved lease is not assigned to a client which
-// identifier doesn't match the identifier in the reservation.
-TEST_F(DORATest, changingCircuitId) {
+TEST_F(DORATest, customServerIdentifier) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ customServerIdentifier();
+}
+
+TEST_F(DORATest, customServerIdentifierMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ customServerIdentifier();
+}
+
+void
+DORATest::changingCircuitId() {
Dhcp4Client client(Dhcp4Client::SELECTING);
client.setHWAddress("aa:bb:cc:dd:ee:ff");
// Use relay agent so as the circuit-id can be inserted.
EXPECT_NE("10.0.0.9", client.config_.lease_.addr_.toText());
}
-// Verifies that extended info is stored on the lease when
-// store-extended-info is enabled.
-TEST_F(DORATest, storeExtendedInfoEnabled) {
+TEST_F(DORATest, changingCircuitId) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ changingCircuitId();
+}
+
+TEST_F(DORATest, changingCircuitIdMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ changingCircuitId();
+}
+
+void
+DORATest::storeExtendedInfoEnabled() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Use relay agent to make sure that the desired subnet is
// selected for our client.
ASSERT_EQ(expected_context, ss.str());
}
-// Verifies that extended info is not stored on the lease when
-// store-extended-info is disabled.
-TEST_F(DORATest, storeExtendedInfoDisabled) {
+TEST_F(DORATest, storeExtendedInfoEnabled) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ storeExtendedInfoEnabled();
+}
+
+TEST_F(DORATest, storeExtendedInfoEnabledMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ storeExtendedInfoEnabled();
+}
+
+void
+DORATest::storeExtendedInfoDisabled() {
Dhcp4Client client(Dhcp4Client::SELECTING);
// Use relay agent to make sure that the desired subnet is
// selected for our client.
ASSERT_FALSE(lease->getContext());
}
+TEST_F(DORATest, storeExtendedInfoDisabled) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ storeExtendedInfoDisabled();
+}
+TEST_F(DORATest, storeExtendedInfoDisabledMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ storeExtendedInfoDisabled();
+}
// Starting tests which require MySQL backend availability. Those tests
// will not be executed if Kea has been compiled without the
// Test that the client using the same hardware address but multiple
// client identifiers will obtain multiple leases (MySQL lease database).
TEST_F(DORAMySQLTest, multiStageBoot) {
- // DORA_CONFIGS[9] to be used for server configuration.
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ // DORA_CONFIGS[8] to be used for server configuration.
+ testMultiStageBoot(8);
+}
+
+// Test that the client using the same hardware address but multiple
+// client identifiers will obtain multiple leases (MySQL lease database).
+TEST_F(DORAMySQLTest, multiStageBootMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ // DORA_CONFIGS[8] to be used for server configuration.
testMultiStageBoot(8);
}
// Test that the client using the same hardware address but multiple
// client identifiers will obtain multiple leases (PostgreSQL lease database).
TEST_F(DORAPgSQLTest, multiStageBoot) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
+ // DORA_CONFIGS[9] to be used for server configuration.
+ testMultiStageBoot(9);
+}
+
+// Test that the client using the same hardware address but multiple
+// client identifiers will obtain multiple leases (PostgreSQL lease database).
+TEST_F(DORAPgSQLTest, multiStageBootMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
// DORA_CONFIGS[9] to be used for server configuration.
testMultiStageBoot(9);
}
// Test that the client using the same hardware address but multiple
// client identifiers will obtain multiple leases (CQL lease database).
TEST_F(DORACQLTest, multiStageBoot) {
+ Dhcpv4SrvMTTestGuard guard(*this, false);
// DORA_CONFIGS[10] to be used for server configuration.
testMultiStageBoot(10);
}
+
+// Test that the client using the same hardware address but multiple
+// client identifiers will obtain multiple leases (CQL lease database).
+TEST_F(DORACQLTest, multiStageBootMultiThreading) {
+ Dhcpv4SrvMTTestGuard guard(*this, true);
+ // DORA_CONFIGS[10] to be used for server configuration.
+ testMultiStageBoot(10);
+}
+
#endif
} // end of anonymous namespace