From: Marcin Siodelski Date: Wed, 2 May 2018 12:41:40 +0000 (+0200) Subject: [master] Merge branch 'trac5458a' X-Git-Tag: trac5488_base~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=04d6fb0a0ac5b9dff2a02764cc9265f9a2a05ae8;p=thirdparty%2Fkea.git [master] Merge branch 'trac5458a' --- 04d6fb0a0ac5b9dff2a02764cc9265f9a2a05ae8 diff --cc src/bin/dhcp6/tests/hooks_unittest.cc index be61642d1f,2b81a88754..3b8d52d0dc --- a/src/bin/dhcp6/tests/hooks_unittest.cc +++ b/src/bin/dhcp6/tests/hooks_unittest.cc @@@ -1642,6 -1728,383 +1728,383 @@@ TEST_F(HooksDhcpv6SrvTest, subnet6Selec ASSERT_EQ(0, srv_->fake_sent_.size()); } + // This test verifies that the leases6_committed hook point is not triggered + // for the SOLICIT. + TEST_F(HooksDhcpv6SrvTest, leases6CommittedSolicit) { + IfaceMgrTestConfig test_config(true); + + string config = "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface\": \"eth1\" " + " } ]," + "\"valid-lifetime\": 4000 }"; + + Dhcp6Client client; + client.setInterface("eth1"); + + ASSERT_NO_THROW(configure(config, *client.getServer())); + + // Install leases6_committed callout + ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( + "leases6_committed", leases6_committed_callout)); + + ASSERT_NO_THROW(client.doSolicit()); + + // Make sure that we received a response + ASSERT_TRUE(client.getContext().response_); + + // Make sure that the callout wasn't called. + EXPECT_TRUE(callback_name_.empty()); + } + + //// Add a positive (vs this negative one) test with Solicit and rapid commit + + //// Looks for the same with park + + // This test verifies that the leases6_committed hook point is not triggered + // for the CONFIRM. + TEST_F(HooksDhcpv6SrvTest, leases6CommittedConfirm) { + IfaceMgrTestConfig test_config(true); + + string config = "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface\": \"eth1\" " + " } ]," + "\"valid-lifetime\": 4000 }"; + + Dhcp6Client client; + client.setInterface("eth1"); + client.requestAddress(0xabca, IOAddress("2001:db8:1::28")); + + ASSERT_NO_THROW(configure(config, *client.getServer())); - ++ + // Get a lease for the client. + ASSERT_NO_THROW(client.doSARR()); - ++ + // Install leases6_committed callout + ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( + "leases6_committed", leases6_committed_callout)); + + ASSERT_NO_THROW(client.doConfirm()); + + // Make sure that we received a response + ASSERT_TRUE(client.getContext().response_); + + // Make sure that the callout wasn't called. + EXPECT_TRUE(callback_name_.empty()); + } + + // This test verifies that the leases6_committed hook point is not triggered + // for the INFREQUEST. + TEST_F(HooksDhcpv6SrvTest, leases6CommittedInfRequest) { + IfaceMgrTestConfig test_config(true); + + string config = "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface\": \"eth1\" " + " } ]," + "\"valid-lifetime\": 4000 }"; + + Dhcp6Client client; + client.useRelay(); + + ASSERT_NO_THROW(configure(config, *client.getServer())); + + ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( + "leases6_committed", leases6_committed_callout)); + + ASSERT_NO_THROW(client.doInfRequest()); + + // Make sure that we received a response + ASSERT_TRUE(client.getContext().response_); + + // Make sure that the callout wasn't called. + EXPECT_TRUE(callback_name_.empty()); + } + + // This test verifies that the callout installed on the leases6_committed hook + // point is executed as a result of REQUEST message sent to allocate new + // lease or renew an existing lease. + TEST_F(HooksDhcpv6SrvTest, leases6CommittedRequest) { + IfaceMgrTestConfig test_config(true); + + string config = "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface\": \"eth1\" " + " } ]," + "\"valid-lifetime\": 4000 }"; + + Dhcp6Client client; + client.setInterface("eth1"); + client.requestAddress(0xabca, IOAddress("2001:db8:1::28")); + + ASSERT_NO_THROW(configure(config, *client.getServer())); + + ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( + "leases6_committed", leases6_committed_callout)); + + ASSERT_NO_THROW(client.doSARR()); + + // Make sure that we received a response + ASSERT_TRUE(client.getContext().response_); + + // Check that the callback called is indeed the one we installed + EXPECT_EQ("leases6_committed", callback_name_); + + // Check if all expected parameters were really received + vector expected_argument_names; + expected_argument_names.push_back("query6"); + expected_argument_names.push_back("deleted_leases6"); + expected_argument_names.push_back("leases6"); + + sort(expected_argument_names.begin(), expected_argument_names.end()); + EXPECT_TRUE(callback_argument_names_ == expected_argument_names); + + // Newly allocated lease should be returned. + ASSERT_TRUE(callback_new_leases6_); + ASSERT_EQ(1, callback_new_leases6_->size()); + Lease6Ptr lease = callback_new_leases6_->at(0); + ASSERT_TRUE(lease); + EXPECT_EQ("2001:db8:1::28", lease->addr_.toText()); + + // Deleted lease must not be present, because it is a new allocation. + ASSERT_TRUE(callback_deleted_leases6_); + EXPECT_TRUE(callback_deleted_leases6_->empty()); + + // Pkt passed to a callout must be configured to copy retrieved options. + EXPECT_TRUE(callback_qry_options_copy_); + + resetCalloutBuffers(); + + // Request the lease and make sure that the callout has been executed. + ASSERT_NO_THROW(client.doRequest()); + + // Make sure that we received a response + ASSERT_TRUE(client.getContext().response_); + + // Check that the callback called is indeed the one we installed + EXPECT_EQ("leases6_committed", callback_name_); + + // Requested lease should be returned. + ASSERT_TRUE(callback_new_leases6_); + ASSERT_EQ(1, callback_new_leases6_->size()); + lease = callback_new_leases6_->at(0); + ASSERT_TRUE(lease); + EXPECT_EQ("2001:db8:1::28", lease->addr_.toText()); + + // Deleted lease must not be present, because it is a new allocation. + ASSERT_TRUE(callback_deleted_leases6_); + EXPECT_TRUE(callback_deleted_leases6_->empty()); + + // Pkt passed to a callout must be configured to copy retrieved options. + EXPECT_TRUE(callback_qry_options_copy_); + + resetCalloutBuffers(); + + // Let's try to request again but force the client to request a different + // address with a different IAID. + client.requestAddress(0x2233, IOAddress("2001:db8:1::29")); + + ASSERT_NO_THROW(client.doRequest()); + + // Make sure that we received a response + ASSERT_TRUE(client.getContext().response_); + + // Check that the callback called is indeed the one we installed + EXPECT_EQ("leases6_committed", callback_name_); + + // New lease should be returned. + ASSERT_TRUE(callback_new_leases6_); + ASSERT_EQ(2, callback_new_leases6_->size()); + lease = callback_new_leases6_->at(1); + ASSERT_TRUE(lease); + EXPECT_EQ("2001:db8:1::29", lease->addr_.toText()); + + // The old lease is kept. + ASSERT_TRUE(callback_deleted_leases6_); + ASSERT_TRUE(callback_deleted_leases6_->empty()); + + // Pkt passed to a callout must be configured to copy retrieved options. + EXPECT_TRUE(callback_qry_options_copy_); + + resetCalloutBuffers(); + + // The requested address is just a hint. + client.requestAddress(0x5577, IOAddress("4000::2")); + + ASSERT_NO_THROW(client.doRequest()); + + // Make sure that we received a response + ASSERT_TRUE(client.getContext().response_); + + // Check that the callback called is indeed the one we installed + EXPECT_EQ("leases6_committed", callback_name_); + + ASSERT_TRUE(callback_new_leases6_); + EXPECT_EQ(3, callback_new_leases6_->size()); + lease = callback_new_leases6_->at(2); + ASSERT_TRUE(lease); + EXPECT_EQ("2001:db8:1::", lease->addr_.toText()); + ASSERT_TRUE(callback_deleted_leases6_); + EXPECT_TRUE(callback_deleted_leases6_->empty()); + + // Pkt passed to a callout must be configured to copy retrieved options. + EXPECT_TRUE(callback_qry_options_copy_); + + resetCalloutBuffers(); + + // Request a prefix: this should lead to an error as no prefix pool + // is configured. + client.requestPrefix(0x1122, 64, IOAddress("2001:db8:1000::")); + + ASSERT_NO_THROW(client.doRequest()); + + // Make sure that we received a response + ASSERT_TRUE(client.getContext().response_); + + // Check the error. + EXPECT_EQ(STATUS_NoPrefixAvail, client.getStatusCode(0x1122)); + + // Check that the callback called is indeed the one we installed + EXPECT_EQ("leases6_committed", callback_name_); + + ASSERT_TRUE(callback_new_leases6_); + EXPECT_EQ(3, callback_new_leases6_->size()); + ASSERT_TRUE(callback_deleted_leases6_); + EXPECT_TRUE(callback_deleted_leases6_->empty()); + } + + //// same with prefix + + // This test verifies that it is possible to park a packet as a result of + // the leases6_committed callouts. + TEST_F(HooksDhcpv6SrvTest, leases6CommittedParkRequests) { + IfaceMgrTestConfig test_config(true); + + string config = "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"interface\": \"eth1\" " + " } ]," + "\"valid-lifetime\": 4000 }"; + + // Create first client and perform SARR. + Dhcp6Client client1; + client1.setInterface("eth1"); + client1.requestAddress(0xabca, IOAddress("2001:db8:1::28")); + + ASSERT_NO_THROW(configure(config, *client1.getServer())); + + // This callout uses provided IO service object to post a function + // that unparks the packet. The packet is parked and can be unparked + // by simply calling IOService::poll. + ASSERT_NO_THROW(HooksManager::preCalloutsLibraryHandle().registerCallout( + "leases6_committed", leases6_committed_park_callout)); + + ASSERT_NO_THROW(client1.doSARR()); + + // We should be offered an address but the REPLY should not arrive + // at this point, because the packet is parked. + ASSERT_FALSE(client1.getContext().response_); + + // Check that the callback called is indeed the one we installed + EXPECT_EQ("leases6_committed", callback_name_); + + // Check if all expected parameters were really received + vector expected_argument_names; + expected_argument_names.push_back("query6"); + expected_argument_names.push_back("deleted_leases6"); + expected_argument_names.push_back("leases6"); + + sort(expected_argument_names.begin(), expected_argument_names.end()); + EXPECT_TRUE(callback_argument_names_ == expected_argument_names); + + // Newly allocated lease should be passed to the callout. + ASSERT_TRUE(callback_new_leases6_); + ASSERT_EQ(1, callback_new_leases6_->size()); + Lease6Ptr lease = callback_new_leases6_->at(0); + ASSERT_TRUE(lease); + EXPECT_EQ("2001:db8:1::28", lease->addr_.toText()); + + // Deleted lease must not be present, because it is a new allocation. + ASSERT_TRUE(callback_deleted_leases6_); + EXPECT_TRUE(callback_deleted_leases6_->empty()); + + // Pkt passed to a callout must be configured to copy retrieved options. + EXPECT_TRUE(callback_qry_options_copy_); + + // Reset all indicators because we'll be now creating a second client. + resetCalloutBuffers(); + + // Create the second client to test that it may communicate with the + // server while the previous packet is parked. + Dhcp6Client client2; + client2.setInterface("eth1"); + client2.requestAddress(0xabca, IOAddress("2001:db8:1::29")); + ASSERT_NO_THROW(client2.doSARR()); + + // The ADVERTISE should have been returned but not REPLAY, as this + // packet got parked too. + ASSERT_FALSE(client2.getContext().response_); + + // Check that the callback called is indeed the one we installed. + EXPECT_EQ("leases6_committed", callback_name_); + + // There should be now two actions scheduled on our IO service + // by the invoked callouts. They unpark both REPLY messages. + ASSERT_NO_THROW(io_service_->poll()); + + // Receive and check the first response. + ASSERT_NO_THROW(client1.receiveResponse()); + ASSERT_TRUE(client1.getContext().response_); + Pkt6Ptr rsp = client1.getContext().response_; + EXPECT_EQ(DHCPV6_REPLY, rsp->getType()); + EXPECT_TRUE(client1.hasLeaseForAddress(IOAddress("2001:db8:1::28"))); + + // Receive and check the second response. + ASSERT_NO_THROW(client2.receiveResponse()); + ASSERT_TRUE(client2.getContext().response_); + rsp = client2.getContext().response_; + EXPECT_EQ(DHCPV6_REPLY, rsp->getType()); + EXPECT_TRUE(client2.hasLeaseForAddress(IOAddress("2001:db8:1::29"))); + } + + //// same with prefix + // This test verifies that incoming (positive) RENEW can be handled properly, // and the lease6_renew callouts are triggered. TEST_F(HooksDhcpv6SrvTest, basicLease6Renew) {