Subnet::Subnet(const isc::asiolink::IOAddress& prefix, uint8_t len,
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
- const Triplet<uint32_t>& valid_lifetime)
- :id_(generateNextID()), prefix_(prefix), prefix_len_(len), t1_(t1),
- t2_(t2), valid_(valid_lifetime),
+ const Triplet<uint32_t>& 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,
}
}
+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_);
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();
const Triplet<uint32_t>& t1,
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& 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");
const Triplet<uint32_t>& t2,
const Triplet<uint32_t>& preferred_lifetime,
const Triplet<uint32_t>& 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
/// 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;
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)
///
/// 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<uint32_t>& t1,
const Triplet<uint32_t>& t2,
- const Triplet<uint32_t>& valid_lifetime);
+ const Triplet<uint32_t>& valid_lifetime,
+ const isc::dhcp::Subnet::RelayInfo& relay);
/// @brief virtual destructor
///
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")));
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);
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));