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<string> 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<string> 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) {