From: Tomek Mrugalski Date: Tue, 28 Jan 2014 18:01:54 +0000 (+0100) Subject: [3274] Relay address can now be stored in Subnet structures. X-Git-Tag: bind10-1.2.0beta1-release~57^2~1^2~20 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=406df0fff274e7ca7ee8a7a13a98195c1073bafa;p=thirdparty%2Fkea.git [3274] Relay address can now be stored in Subnet structures. --- diff --git a/src/lib/dhcpsrv/subnet.cc b/src/lib/dhcpsrv/subnet.cc index 0134d8c9ac..7e56dbbb57 100644 --- a/src/lib/dhcpsrv/subnet.cc +++ b/src/lib/dhcpsrv/subnet.cc @@ -30,12 +30,14 @@ SubnetID Subnet::static_id_ = 1; Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len, const Triplet& t1, const Triplet& t2, - const Triplet& valid_lifetime) - :id_(generateNextID()), prefix_(prefix), prefix_len_(len), t1_(t1), - t2_(t2), valid_(valid_lifetime), + const Triplet& valid_lifetime, + const isc::dhcp::Subnet::RelayInfo& relay) + :relay_(relay), id_(generateNextID()), prefix_(prefix), prefix_len_(len), + t1_(t1), t2_(t2), valid_(valid_lifetime), last_allocated_ia_(lastAddrInPrefix(prefix, len)), last_allocated_ta_(lastAddrInPrefix(prefix, len)), - last_allocated_pd_(lastAddrInPrefix(prefix, len)) { + last_allocated_pd_(lastAddrInPrefix(prefix, len)) + { if ((prefix.isV6() && len > 128) || (prefix.isV4() && len > 32)) { isc_throw(BadValue, @@ -43,6 +45,10 @@ Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len, } } +Subnet::RelayInfo::RelayInfo(const isc::asiolink::IOAddress& addr) + :addr_(addr) { +} + bool Subnet::inRange(const isc::asiolink::IOAddress& addr) const { IOAddress first = firstAddrInPrefix(prefix_, prefix_len_); @@ -65,6 +71,11 @@ Subnet::addOption(const OptionPtr& option, bool persistent, option_spaces_.addItem(OptionDescriptor(option, persistent), option_space); } +void +Subnet::setRelay(const isc::dhcp::Subnet::RelayInfo& relay) { + relay_ = relay; +} + void Subnet::delOptions() { option_spaces_.clearItems(); @@ -179,8 +190,8 @@ Subnet4::Subnet4(const isc::asiolink::IOAddress& prefix, uint8_t length, const Triplet& t1, const Triplet& t2, const Triplet& valid_lifetime) - :Subnet(prefix, length, t1, t2, valid_lifetime), - siaddr_(IOAddress("0.0.0.0")) { +:Subnet(prefix, length, t1, t2, valid_lifetime, + RelayInfo(IOAddress("0.0.0.0"))), siaddr_(IOAddress("0.0.0.0")) { if (!prefix.isV4()) { isc_throw(BadValue, "Non IPv4 prefix " << prefix.toText() << " specified in subnet4"); @@ -331,7 +342,7 @@ Subnet6::Subnet6(const isc::asiolink::IOAddress& prefix, uint8_t length, const Triplet& t2, const Triplet& preferred_lifetime, const Triplet& valid_lifetime) - :Subnet(prefix, length, t1, t2, valid_lifetime), +:Subnet(prefix, length, t1, t2, valid_lifetime, RelayInfo(IOAddress("::"))), preferred_(preferred_lifetime){ if (!prefix.isV6()) { isc_throw(BadValue, "Non IPv6 prefix " << prefix diff --git a/src/lib/dhcpsrv/subnet.h b/src/lib/dhcpsrv/subnet.h index ecac6c3af8..5373ebca49 100644 --- a/src/lib/dhcpsrv/subnet.h +++ b/src/lib/dhcpsrv/subnet.h @@ -166,6 +166,23 @@ public: /// Type of the index #2 - option persistency flag. typedef OptionContainer::nth_index<2>::type OptionContainerPersistIndex; + /// @brief Holds optional information about relay. + /// + /// In some cases it is beneficial to have additional information about + /// a relay configured in the subnet. For now, the structure holds only + /// IP address, but there may potentially be additional parameters added + /// later, e.g. relay interface-id or relay-id. + struct RelayInfo { + + /// @brief default and the only constructor + /// + /// @param addr an IP address of the relay (may be :: or 0.0.0.0) + RelayInfo(const isc::asiolink::IOAddress& addr); + + /// @brief IP address of the relay + isc::asiolink::IOAddress addr_; + }; + /// @brief checks if specified address is in range bool inRange(const isc::asiolink::IOAddress& addr) const; @@ -375,6 +392,33 @@ public: static_id_ = 1; } + /// @brief Sets address of the relay + /// + /// In some situations where there are shared subnets (i.e. two different + /// subnets are available on the same physical link), there is only one + /// relay that handles incoming requests from clients. In such a case, + /// the usual subnet selection criteria based on relay belonging to the + /// subnet being selected are no longer sufficient and we need to explicitly + /// specify a relay. One notable example of such uncommon, but valid + /// scenario is a cable network, where there is only one CMTS (one relay), + /// but there are 2 distinct subnets behind it: one for cable modems + /// and another one for CPEs and other user equipment behind modems. + /// From manageability perspective, it is essential that modems get addresses + /// from different subnet, so users won't tinker with their modems. + /// + /// Setting this parameter is not needed in most deployments. + /// + /// @params relay IP address of the relay + void setRelay(const isc::dhcp::Subnet::RelayInfo& relay); + + /// @brief Relay information + /// + /// See @ref RelayInfo for detailed description. This structure is public, + /// so its fields are easily accessible. Making it protected would bring in + /// the issue of returning references that may become stale after its parent + /// subnet object disappears. + RelayInfo relay_; + protected: /// @brief Returns all pools (non-const variant) /// @@ -393,10 +437,18 @@ protected: /// This subnet-id has unique value that is strictly monotonously increasing /// for each subnet, until it is explicitly reset back to 1 during /// reconfiguration process. + /// + /// @param prefix subnet prefix + /// @param len prefix length for the subnet + /// @param t1 T1 (renewal-time) timer, expressed in seconds + /// @param t2 T2 (rebind-time) timer, expressed in seconds + /// @param valid_lifetime valid lifetime of leases in this subnet (in seconds) + /// @param relay optional relay information (currently with address only) Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len, const Triplet& t1, const Triplet& t2, - const Triplet& valid_lifetime); + const Triplet& valid_lifetime, + const isc::dhcp::Subnet::RelayInfo& relay); /// @brief virtual destructor /// diff --git a/src/lib/dhcpsrv/tests/subnet_unittest.cc b/src/lib/dhcpsrv/tests/subnet_unittest.cc index d0dd57a3dd..9392d3c60b 100644 --- a/src/lib/dhcpsrv/tests/subnet_unittest.cc +++ b/src/lib/dhcpsrv/tests/subnet_unittest.cc @@ -49,6 +49,8 @@ TEST(Subnet4Test, in_range) { EXPECT_EQ(2000, subnet.getT2()); EXPECT_EQ(3000, subnet.getValid()); + EXPECT_EQ("0.0.0.0", subnet.relay_.addr_.toText()); + EXPECT_FALSE(subnet.inRange(IOAddress("192.0.0.0"))); EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.0"))); EXPECT_TRUE(subnet.inRange(IOAddress("192.0.2.1"))); @@ -58,6 +60,17 @@ TEST(Subnet4Test, in_range) { EXPECT_FALSE(subnet.inRange(IOAddress("255.255.255.255"))); } +// Checks whether the relay field has sane default and if it can +// be changed, stored and retrieved +TEST(Subnet4Test, relay) { + Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000); + + EXPECT_EQ("0.0.0.0", subnet.relay_.addr_.toText()); + + subnet.setRelay(IOAddress("192.0.123.45")); + EXPECT_EQ("192.0.123.45", subnet.relay_.addr_.toText()); +} + // Checks whether siaddr field can be set and retrieved correctly. TEST(Subnet4Test, siaddr) { Subnet4 subnet(IOAddress("192.0.2.1"), 24, 1000, 2000, 3000); @@ -291,6 +304,18 @@ TEST(Subnet6Test, in_range) { EXPECT_FALSE(subnet.inRange(IOAddress("::"))); } +// Checks whether the relay field has sane default and if it can +// be changed, stored and retrieved +TEST(Subnet6Test, relay) { + Subnet6 subnet(IOAddress("2001:db8:1::"), 64, 1000, 2000, 3000, 4000); + + EXPECT_EQ("::", subnet.relay_.addr_.toText()); + + subnet.setRelay(IOAddress("2001:ffff::1")); + + EXPECT_EQ("2001:ffff::1", subnet.relay_.addr_.toText()); +} + TEST(Subnet6Test, Pool6InSubnet6) { Subnet6Ptr subnet(new Subnet6(IOAddress("2001:db8:1::"), 56, 1, 2, 3, 4));