From: Tomek Mrugalski Date: Mon, 16 Feb 2015 19:26:38 +0000 (+0100) Subject: [master] Merge branch 'trac3565' (host reservations mac+dhcpv6) X-Git-Tag: trac3723_base~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cfbe13ad05aac23e09357fc78507cf9a82c908e6;p=thirdparty%2Fkea.git [master] Merge branch 'trac3565' (host reservations mac+dhcpv6) Conflicts: src/bin/dhcp6/dhcp6_srv.cc --- cfbe13ad05aac23e09357fc78507cf9a82c908e6 diff --cc src/bin/dhcp4/tests/config_parser_unittest.cc index 7dd17be787,f1cc849c64..2be8a29747 --- a/src/bin/dhcp4/tests/config_parser_unittest.cc +++ b/src/bin/dhcp4/tests/config_parser_unittest.cc @@@ -3496,8 -3478,79 +3496,79 @@@ TEST_F(Dhcp4ParserTest, reservationBogu EXPECT_NO_THROW(x = configureDhcp4Server(*srv_, json)); checkResult(x, 1); + } + /// The goal of this test is to verify that Host Reservation modes can be + /// specified on a per-subnet basis. + TEST_F(Dhcp4ParserTest, hostReservationPerSubnet) { + /// - Configuration: + /// - only addresses (no prefixes) + /// - 4 subnets with: + /// - 192.0.2.0/24 (all reservations enabled) + /// - 192.0.3.0/24 (out-of-pool reservations) + /// - 192.0.4.0/24 (reservations disabled) + /// - 192.0.5.0/24 (reservations not specified) + const char* hr_config = - "{ \"interfaces\": [ \"*\" ]," ++ "{ " + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet4\": [ { " + " \"pools\": [ { \"pool\": \"192.0.2.0/24\" } ]," + " \"subnet\": \"192.0.2.0/24\", " + " \"reservation-mode\": \"all\"" + " }," + " {" + " \"pools\": [ { \"pool\": \"192.0.3.0/24\" } ]," + " \"subnet\": \"192.0.3.0/24\", " + " \"reservation-mode\": \"out-of-pool\"" + " }," + " {" + " \"pools\": [ { \"pool\": \"192.0.4.0/24\" } ]," + " \"subnet\": \"192.0.4.0/24\", " + " \"reservation-mode\": \"disabled\"" + " }," + " {" + " \"pools\": [ { \"pool\": \"192.0.5.0/24\" } ]," + " \"subnet\": \"192.0.5.0/24\"" + " } ]," + "\"valid-lifetime\": 4000 }"; + + ElementPtr json = Element::fromJSON(hr_config); + ConstElementPtr result; + EXPECT_NO_THROW(result = configureDhcp4Server(*srv_, json)); + + // returned value should be 0 (success) + checkResult(result, 0); + + // Let's get all subnets and check that there are 4 of them. + ConstCfgSubnets4Ptr subnets = CfgMgr::instance().getStagingCfg()->getCfgSubnets4(); + ASSERT_TRUE(subnets); + const Subnet4Collection* subnet_col = subnets->getAll(); + ASSERT_EQ(4, subnet_col->size()); // We expect 4 subnets + + // Let's check if the parsed subnets have correct HR modes. + + // Subnet 1 + Subnet4Ptr subnet; + subnet = subnets->selectSubnet(IOAddress("192.0.2.1")); + ASSERT_TRUE(subnet); + EXPECT_EQ(Subnet::HR_ALL, subnet->getHostReservationMode()); + + // Subnet 2 + subnet = subnets->selectSubnet(IOAddress("192.0.3.1")); + ASSERT_TRUE(subnet); + EXPECT_EQ(Subnet::HR_OUT_OF_POOL, subnet->getHostReservationMode()); + + // Subnet 3 + subnet = subnets->selectSubnet(IOAddress("192.0.4.1")); + ASSERT_TRUE(subnet); + EXPECT_EQ(Subnet::HR_DISABLED, subnet->getHostReservationMode()); + + // Subnet 4 + subnet = subnets->selectSubnet(IOAddress("192.0.5.1")); + ASSERT_TRUE(subnet); + EXPECT_EQ(Subnet::HR_ALL, subnet->getHostReservationMode()); } } diff --cc src/bin/dhcp6/dhcp6_srv.cc index 5dbec66b68,c1460df327..3483808e45 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@@ -1574,12 -1581,21 +1574,21 @@@ Dhcpv6Srv::extendIA_NA(const Subnet6Ptr continue; } ctx.hints_.push_back(make_pair(iaaddr->getAddress(), 128)); - - // We need to remember it as we'll be removing hints from this list as - // we extend, cancel or otherwise deal with the leases. - hints_count++; } + // We need to remember it as we'll be removing hints from this list as + // we extend, cancel or otherwise deal with the leases. + bool hints_present = !ctx.hints_.empty(); + + /// @todo: This was clarfied in draft-ietf-dhc-dhcpv6-stateful-issues that + /// the server is allowed to assign new leases in both Renew and Rebind. For + /// now, we only support it in Renew, because it breaks a lot of Rebind + /// unit-tests. Ultimately, whether we allow it or not, should be exposed + /// as configurable policy. See ticket #3717. + if (query->getType() == DHCPV6_RENEW) { + ctx.allow_new_leases_in_renewals_ = true; + } + Lease6Collection leases = alloc_engine_->renewLeases6(ctx); // Ok, now we have the leases extended. We have: @@@ -1742,11 -1754,18 +1751,17 @@@ Dhcpv6Srv::extendIA_PD(const Subnet6Ptr // Put the client's prefix into the hints list. ctx.hints_.push_back(make_pair(prf->getAddress(), prf->getLength())); - - // We need to remember it as we'll be removing hints from this list as - // we extend, cancel or otherwise deal with the leases. - hints_count++; } + // We need to remember it as we'll be removing hints from this list as + // we extend, cancel or otherwise deal with the leases. + bool hints_present = !ctx.hints_.empty(); + /// @todo: The draft-ietf-dhc-dhcpv6-stateful-issues added a new capability + /// of the server to to assign new PD leases in both Renew and Rebind. + /// There's allow_new_leases_in_renewals_ in the ClientContext6, but we + /// currently not use it in PD yet. This should be implemented as part + /// of the stateful-issues implementation effort. See ticket #3718. + // Call Allocation Engine and attempt to renew leases. Number of things // may happen. Leases may be extended, revoked (if the lease is no longer // valid or reserved for someone else), or new leases may be added. diff --cc src/bin/dhcp6/tests/config_parser_unittest.cc index 95f914e2b3,25d273a8b7..0f511b4fee --- a/src/bin/dhcp6/tests/config_parser_unittest.cc +++ b/src/bin/dhcp6/tests/config_parser_unittest.cc @@@ -3703,4 -3691,80 +3703,80 @@@ TEST_F(Dhcp6ParserTest, macSourcesBogus checkResult(status, 1); } + /// The goal of this test is to verify that Host Reservation modes can be + /// specified on a per-subnet basis. + TEST_F(Dhcp6ParserTest, hostReservationPerSubnet) { + + /// - Configuration: + /// - only addresses (no prefixes) + /// - 4 subnets with: + /// - 2001:db8:1::/64 (all reservations enabled) + /// - 2001:db8:2::/64 (out-of-pool reservations) + /// - 2001:db8:3::/64 (reservations disabled) + /// - 2001:db8:3::/64 (reservations not specified) + const char* HR_CONFIG = - "{ \"interfaces\": [ \"*\" ]," ++ "{" + "\"preferred-lifetime\": 3000," + "\"rebind-timer\": 2000, " + "\"renew-timer\": 1000, " + "\"subnet6\": [ { " + " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," + " \"subnet\": \"2001:db8:1::/48\", " + " \"reservation-mode\": \"all\"" + " }," + " {" + " \"pools\": [ { \"pool\": \"2001:db8:2::/64\" } ]," + " \"subnet\": \"2001:db8:2::/48\", " + " \"reservation-mode\": \"out-of-pool\"" + " }," + " {" + " \"pools\": [ { \"pool\": \"2001:db8:3::/64\" } ]," + " \"subnet\": \"2001:db8:3::/48\", " + " \"reservation-mode\": \"disabled\"" + " }," + " {" + " \"pools\": [ { \"pool\": \"2001:db8:4::/64\" } ]," + " \"subnet\": \"2001:db8:4::/48\" " + " } ]," + "\"valid-lifetime\": 4000 }"; + + ConstElementPtr status; + + EXPECT_NO_THROW(status = configureDhcp6Server(srv_, + Element::fromJSON(HR_CONFIG))); + + // returned value should be 0 (success) + checkResult(status, 0); + CfgMgr::instance().commit(); + + // Let's get all subnets and check that there are 4 of them. + ConstCfgSubnets6Ptr subnets = CfgMgr::instance().getCurrentCfg()->getCfgSubnets6(); + ASSERT_TRUE(subnets); + const Subnet6Collection* subnet_col = subnets->getAll(); + ASSERT_EQ(4, subnet_col->size()); // We expect 4 subnets + + // Let's check if the parsed subnets have correct HR modes. + + // Subnet 1 + Subnet6Ptr subnet; + subnet = subnets->selectSubnet(IOAddress("2001:db8:1::1")); + ASSERT_TRUE(subnet); + EXPECT_EQ(Subnet::HR_ALL, subnet->getHostReservationMode()); + + // Subnet 2 + subnet = subnets->selectSubnet(IOAddress("2001:db8:2::1")); + ASSERT_TRUE(subnet); + EXPECT_EQ(Subnet::HR_OUT_OF_POOL, subnet->getHostReservationMode()); + + // Subnet 3 + subnet = subnets->selectSubnet(IOAddress("2001:db8:3::1")); + ASSERT_TRUE(subnet); + EXPECT_EQ(Subnet::HR_DISABLED, subnet->getHostReservationMode()); + + // Subnet 4 + subnet = subnets->selectSubnet(IOAddress("2001:db8:4::1")); + ASSERT_TRUE(subnet); + EXPECT_EQ(Subnet::HR_ALL, subnet->getHostReservationMode()); + } + };