From: Francis Dupont Date: Sun, 31 Mar 2024 20:55:45 +0000 (+0200) Subject: [#2976] Added DORA+RENEW tests X-Git-Tag: Kea-2.5.8~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=836bc517055e163d29db1074a98e1d80db8c23bc;p=thirdparty%2Fkea.git [#2976] Added DORA+RENEW tests --- diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index d385812690..0b16a9d5a4 100644 --- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc +++ b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc @@ -5586,7 +5586,7 @@ TEST_F(StashAgentOptionTest, relayAgentInfoEntry) { EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS")); } -// Verify the relay-agent-info entry must be a map or a string. +// Verify that the relay-agent-info entry must be a map or a string. TEST_F(StashAgentOptionTest, badRelayAgentInfoEntry) { // Set the relay-agent-info entry to a boolean. relay_agent_info_ = Element::create(true); @@ -5601,7 +5601,7 @@ TEST_F(StashAgentOptionTest, badRelayAgentInfoEntry) { EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS")); } -// Verify the sub-options entry is required in new extended info format. +// Verify that the sub-options entry is required in new extended info format. TEST_F(StashAgentOptionTest, subOptionsEntry) { // Remove the sub-options entry. relay_agent_info_ = Element::createMap(); @@ -5617,7 +5617,7 @@ TEST_F(StashAgentOptionTest, subOptionsEntry) { EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS")); } -// Verify the sub-options entry must be a string. +// Verify that the sub-options entry must be a string. TEST_F(StashAgentOptionTest, badSubOptionsEntry) { // Set the sub-options entry to a boolean. sub_options_ = Element::create(true); @@ -5632,7 +5632,7 @@ TEST_F(StashAgentOptionTest, badSubOptionsEntry) { EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS")); } -// Verify the sub-options entry must be not empty. +// Verify that the sub-options entry must be not empty. TEST_F(StashAgentOptionTest, emptySubOptionsEntry) { // Set the sub-options entry to empty. sub_options_ = Element::create(""); @@ -5647,7 +5647,7 @@ TEST_F(StashAgentOptionTest, emptySubOptionsEntry) { EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS")); } -// Verify the sub-options entry must be a valid hexstring. +// Verify that the sub-options entry must be a valid hexstring. TEST_F(StashAgentOptionTest, hexString) { // Set the sub-options entry to invalid hexstring. sub_options_ = Element::create("foobar"); @@ -5660,7 +5660,7 @@ TEST_F(StashAgentOptionTest, hexString) { EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS")); } -// Verify the sub-options entry must be a valid RAI content. +// Verify that the sub-options entry must be a valid RAI content. TEST_F(StashAgentOptionTest, badRelayAgentInfo) { // Set the sub-options entry to truncated RAI content. string content = sub_options_->stringValue(); @@ -5690,6 +5690,42 @@ TEST_F(StashAgentOptionTest, badRelayAgentInfo) { EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS")); } +// Verify that the client id when set must match. +TEST_F(StashAgentOptionTest, badClientId) { + // Use another the client id. + query_->delOption(DHO_DHCP_CLIENT_IDENTIFIER); + query_->addOption(generateClientId(8)); + + CfgMgr::instance().commit(); + EXPECT_NO_THROW(LeaseMgrFactory::instance().addLease(lease_)); + + EXPECT_NO_THROW(srv_.recoverStashedAgentOption(query_)); + OptionPtr rai_query = query_->getOption(DHO_DHCP_AGENT_OPTIONS); + EXPECT_FALSE(rai_query); + EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS")); +} + +// Verify that when the client id is not used the hardware address must match. +TEST_F(StashAgentOptionTest, badHwareAddress) { + // No longer use the client id. + query_->delOption(DHO_DHCP_CLIENT_IDENTIFIER); + lease_.reset(new Lease4(addr_, hwaddr_, ClientIdPtr(), 100, time(0), 1)); + lease_->setContext(user_context_); + + // Change the hardware address. + auto hwaddr2 = generateHWAddr(8); + ASSERT_NE(hwaddr_, hwaddr2); + query_->setHWAddr(hwaddr2); + + CfgMgr::instance().commit(); + EXPECT_NO_THROW(LeaseMgrFactory::instance().addLease(lease_)); + + EXPECT_NO_THROW(srv_.recoverStashedAgentOption(query_)); + OptionPtr rai_query = query_->getOption(DHO_DHCP_AGENT_OPTIONS); + EXPECT_FALSE(rai_query); + EXPECT_FALSE(query_->inClass("STASH_AGENT_OPTIONS")); +} + /// @todo: lease ownership /// @todo: Implement proper tests for MySQL lease/host database, diff --git a/src/bin/dhcp4/tests/dora_unittest.cc b/src/bin/dhcp4/tests/dora_unittest.cc index 9520f14d2b..bc0122b8ab 100644 --- a/src/bin/dhcp4/tests/dora_unittest.cc +++ b/src/bin/dhcp4/tests/dora_unittest.cc @@ -167,6 +167,20 @@ namespace { /// - Configuration 20: /// - No subnets. /// - Global authoritative flag is true. +/// +/// - Configuration 21: +/// - Use for testing stash agent options (flag true). +/// - 1 subnet with storing extended info enabled +/// +/// - Configuration 22: +/// - Use for testing stash agent options (flag true). +/// - 1 subnet with storing extended info enabled +/// - 1 reservation using the circuit-id +/// +/// - Configuration 23: +/// - Use for testing stash agent options (flag false). +/// - 1 subnet with storing extended info enabled +/// - 1 reservation using the circuit-id const char* DORA_CONFIGS[] = { // Configuration 0 "{ \"interfaces-config\": {" @@ -649,6 +663,54 @@ const char* DORA_CONFIGS[] = { "\"authoritative\": true," "\"subnet4\": []" "}", + + // Configuration 21 + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"valid-lifetime\": 600," + "\"stash-agent-options\": true," + "\"subnet4\": [ {" + " \"subnet\": \"10.0.0.0/24\", " + " \"id\": 1, " + " \"store-extended-info\": true," + " \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]" + "} ]" + "}", + + // Configuration 22 + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"valid-lifetime\": 600," + "\"stash-agent-options\": true," + "\"host-reservation-identifiers\": [ \"circuit-id\" ]," + "\"subnet4\": [ {" + " \"subnet\": \"10.0.0.0/24\", " + " \"id\": 1, " + " \"store-extended-info\": true," + " \"reservations\": [ {" + " \"circuit-id\": \"'charter950'\"," + " \"ip-address\": \"10.0.0.9\" } ]" + "} ]" + "}", + + // Configuration 23 + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"valid-lifetime\": 600," + "\"stash-agent-options\": false," + "\"host-reservation-identifiers\": [ \"circuit-id\" ]," + "\"subnet4\": [ {" + " \"subnet\": \"10.0.0.0/24\", " + " \"id\": 1, " + " \"store-extended-info\": true," + " \"reservations\": [ {" + " \"circuit-id\": \"'charter950'\"," + " \"ip-address\": \"10.0.0.9\" } ]" + "} ]" + "}", }; /// @brief Test fixture class for testing 4-way (DORA) exchanges. @@ -911,6 +973,22 @@ public: /// @brief Checks that features related to lease caching (such as lease reuse statistics) work. void leaseCaching(); + /// @brief Checks that stash-agent-options enables direct renewall + /// of addresses from pool allocation for a relayed client. + /// + /// @note: no negative counterpart as the stash-agent-options is not + /// required for this scenario. + void stashAgentOptions(); + + /// @brief Checks that stash-agent-options enables direct renewall + /// of addresses from host reservation using the relay-agent-info option. + void stashAgentOptionsReservation(); + + /// @brief Checks that stash-agent-options is required for direct + /// renewall of addresses from host reservation using the + /// relay-agent-info option. + void noStashAgentOptionsReservation(); + /// @brief Checks the value of a statistic. /// /// @param name name of statistic to check @@ -3085,6 +3163,145 @@ TEST_F(DORATest, leaseCachingMultiThreading) { leaseCaching(); } +void +DORATest::stashAgentOptions() { + Dhcp4Client client(Dhcp4Client::SELECTING); + // Use relay agent to make sure that the desired subnet is + // selected for our client. + client.useRelay(true, IOAddress("10.0.0.20"), IOAddress("10.0.0.21")); + // Specify client identifier. + client.includeClientId("01:11:22:33:44:55:66"); + // Set the circuit id. + client.setCircuitId("charter950"); + + // Configure DHCP server. + configure(DORA_CONFIGS[21], *client.getServer()); + // Perform 4-way exchange and should obtain an address from pool. + ASSERT_NO_THROW_LOG(client.doDORA()); + // Make sure that the server responded. + ASSERT_TRUE(client.getContext().response_); + Pkt4Ptr resp = client.getContext().response_; + // Make sure that the server has responded with DHCPACK. + ASSERT_EQ(DHCPACK, static_cast(resp->getType())); + // Make sure that the client has got the lease for the first address + // of the pool. + ASSERT_EQ("10.0.0.10", client.config_.lease_.addr_.toText()); + + // Renew. + client.setState(Dhcp4Client::RENEWING); + // Set the unicast destination address to indicate that it is a renewal. + client.setDestAddress(IOAddress("10.0.0.1")); + // Disable relay. + client.useRelay(false); + ASSERT_NO_THROW_LOG(client.doRequest()); + ASSERT_TRUE(client.getContext().response_); + resp = client.getContext().response_; + ASSERT_EQ(DHCPACK, static_cast(resp->getType())); + ASSERT_EQ("10.0.0.10", client.config_.lease_.addr_.toText()); +} + +TEST_F(DORATest, stashAgentOptions) { + Dhcpv4SrvMTTestGuard guard(*this, false); + stashAgentOptions(); +} + +TEST_F(DORATest, stashAgentOptionsMultiThreading) { + Dhcpv4SrvMTTestGuard guard(*this, true); + stashAgentOptions(); +} + +void +DORATest::stashAgentOptionsReservation() { + Dhcp4Client client(Dhcp4Client::SELECTING); + // Use relay agent to make sure that the desired subnet is + // selected for our client. + client.useRelay(true, IOAddress("10.0.0.20"), IOAddress("10.0.0.21")); + // Specify client identifier. + client.includeClientId("01:11:22:33:44:55:66"); + // Set the circuit id. + client.setCircuitId("charter950"); + + // Configure DHCP server. + configure(DORA_CONFIGS[22], *client.getServer()); + // Perform 4-way exchange and should obtain the reserved address. + ASSERT_NO_THROW_LOG(client.doDORA()); + // Make sure that the server responded. + ASSERT_TRUE(client.getContext().response_); + Pkt4Ptr resp = client.getContext().response_; + // Make sure that the server has responded with DHCPACK. + ASSERT_EQ(DHCPACK, static_cast(resp->getType())); + // Make sure that the client has got the lease for the reserved address. + ASSERT_EQ("10.0.0.9", client.config_.lease_.addr_.toText()); + + // Renew. + client.setState(Dhcp4Client::RENEWING); + // Set the unicast destination address to indicate that it is a renewal. + client.setDestAddress(IOAddress("10.0.0.1")); + // Disable relay. + client.useRelay(false); + ASSERT_NO_THROW_LOG(client.doRequest()); + ASSERT_TRUE(client.getContext().response_); + resp = client.getContext().response_; + ASSERT_EQ(DHCPACK, static_cast(resp->getType())); + ASSERT_EQ("10.0.0.9", client.config_.lease_.addr_.toText()); +} + +TEST_F(DORATest, stashAgentOptionsReservation) { + Dhcpv4SrvMTTestGuard guard(*this, false); + stashAgentOptionsReservation(); +} + +TEST_F(DORATest, stashAgentOptionsReservationMultiThreading) { + Dhcpv4SrvMTTestGuard guard(*this, true); + stashAgentOptionsReservation(); +} + +void +DORATest::noStashAgentOptionsReservation() { + Dhcp4Client client(Dhcp4Client::SELECTING); + // Use relay agent to make sure that the desired subnet is + // selected for our client. + client.useRelay(true, IOAddress("10.0.0.20"), IOAddress("10.0.0.21")); + // Specify client identifier. + client.includeClientId("01:11:22:33:44:55:66"); + // Set the circuit id. + client.setCircuitId("charter950"); + + // Configure DHCP server. + configure(DORA_CONFIGS[23], *client.getServer()); + // Perform 4-way exchange and should obtain the reserved address. + ASSERT_NO_THROW_LOG(client.doDORA()); + // Make sure that the server responded. + ASSERT_TRUE(client.getContext().response_); + Pkt4Ptr resp = client.getContext().response_; + // Make sure that the server has responded with DHCPACK. + ASSERT_EQ(DHCPACK, static_cast(resp->getType())); + // Make sure that the client has got the lease for the reserved address. + ASSERT_EQ("10.0.0.9", client.config_.lease_.addr_.toText()); + + // Renew. + client.setState(Dhcp4Client::RENEWING); + // Set the unicast destination address to indicate that it is a renewal. + client.setDestAddress(IOAddress("10.0.0.1")); + // Disable relay. + client.useRelay(false); + ASSERT_NO_THROW_LOG(client.doRequest()); + ASSERT_TRUE(client.getContext().response_); + resp = client.getContext().response_; + // The client is not recognized so a NAK is returned. + ASSERT_EQ(DHCPNAK, static_cast(resp->getType())); +} + +TEST_F(DORATest, noStashAgentOptionsReservation) { + Dhcpv4SrvMTTestGuard guard(*this, false); + noStashAgentOptionsReservation(); +} + +TEST_F(DORATest, noStashAgentOptionsReservationMultiThreading) { + Dhcpv4SrvMTTestGuard guard(*this, true); + noStashAgentOptionsReservation(); +} + /// @brief Checks the value of a statistic. /// /// @param name name of statistic to check