55// file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
77#include < config.h>
8+ #include < asiolink/addr_utilities.h>
89#include < dhcpsrv/free_lease_queue.h>
9- #include < exceptions/exceptions.h>
1010
1111#include < boost/make_shared.hpp>
1212
1313#include < iostream>
14- #include < iterator>
1514#include < tuple>
1615#include < utility>
1716
@@ -29,48 +28,9 @@ FreeLeaseQueue::addRange(const Range& range) {
2928 // If the container with ranges is empty, there are is no need for
3029 // doing any checks. Let's just add the new range.
3130 if (!containers_.empty ()) {
32- // Get the next range in the container relative to the start of the new
33- // range. The upper_bound returns the range which starts after the start
34- // of the new range.
35- auto next_range = containers_.lower_bound (range.start_ );
36- // Get the range the range that is before that one. It is also possible that
37- // there is no previous range in which case we default to end().
38- auto previous_range = containers_.end ();
39- // If the next range is at the beginning of the container there is no
40- // previous range.
41- if (next_range != containers_.begin ()) {
42- // This should work fine even if the next range is set to end(). We
43- // will get the range that is one position before end() and that
44- // should be the range that goes before the new one.
45- auto it = next_range;
46- --it;
47- previous_range = it;
48- }
49-
50- // Now that we have next and previous ranges set we should check that the
51- // new range we're adding does not overlap with them.
52-
53- // If the previous range exists, let's check that the start of the new
54- // range is neither within that range nor lower. Assuming that the ranges
55- // are constructed such that the end must be greater or equal the start
56- // it is sufficient to check that the start of the new range is not lower
57- // or equal the end of the previous range.
58- if ((previous_range != containers_.end ()) &&
59- (range.start_ <= previous_range->range_end_ )) {
60- isc_throw (BadValue, " new address range " << range.start_ << " :" << range.end_
61- << " overlaps with the existing range" );
62- }
63-
64- // If the next range exists, let's check that the end of the new range
65- // is neither within that range nor higher.
66- if ((next_range != containers_.end ()) &&
67- (next_range->range_start_ <= range.end_ )) {
68- isc_throw (BadValue, " new address range " << range.start_ << " :" << range.end_
69- << " overlaps with the existing range" );
70- }
71- }
72-
73- containers_.insert (ContainerDescriptor{range.start_ , range.end_ ,
31+ checkRangeOverlaps (range.start_ , range.end_ );
32+ }
33+ containers_.insert (ContainerDescriptor{range.start_ , range.end_ , 128 ,
7434 boost::make_shared<Container>()});
7535}
7636
@@ -79,9 +39,20 @@ FreeLeaseQueue::addRange(const IOAddress& start, const IOAddress& end) {
7939 addRange (FreeLeaseQueue::Range (start, end));
8040}
8141
82- bool
83- FreeLeaseQueue::removeRange (const Range& range) {
84- return (containers_.get <1 >().erase (range.start_ ) > 0 );
42+ void
43+ FreeLeaseQueue::addRange (const PrefixRange& range) {
44+ if (!containers_.empty ()) {
45+ auto last_addr = offsetAddress (range.end_ , range.delegated_length_ - 1 );
46+ checkRangeOverlaps (range.start_ , last_addr);
47+ }
48+ containers_.insert (ContainerDescriptor{range.start_ , range.end_ , range.delegated_length_ ,
49+ boost::make_shared<Container>()});
50+ }
51+
52+ void
53+ FreeLeaseQueue::addRange (const asiolink::IOAddress& prefix, const uint8_t prefix_length,
54+ const uint8_t delegated_length) {
55+ addRange (FreeLeaseQueue::PrefixRange (prefix, prefix_length, delegated_length));
8556}
8657
8758bool
@@ -112,33 +83,63 @@ FreeLeaseQueue::append(const IOAddress& address) {
11283 return (true );
11384}
11485
86+ bool
87+ FreeLeaseQueue::append (const IOAddress& prefix, const uint8_t delegated_length) {
88+ // If there are no ranges defined, there is nothing to do.
89+ if (containers_.empty ()) {
90+ return (false );
91+ }
92+ // Find the beginning of the range which has the start address
93+ // greater than the address we're appending.
94+ auto lb = containers_.upper_bound (prefix);
95+ // If the range we found is the first one in the container
96+ // there is no range matching our prefix because all existing
97+ // ranges include higher addresses.
98+ if (lb == containers_.begin ()) {
99+ return (false );
100+ }
101+ --lb;
102+ // Go one range back and see if our prefix is within its boundaries.
103+ if ((lb->range_end_ < prefix) || (prefix < lb->range_start_ ) ||
104+ (delegated_length != lb->delegated_length_ )) {
105+ return (false );
106+ }
107+ // Use the range we found and append the prefix to it.
108+ FreeLeaseQueue::PrefixRange range (lb->range_start_ , lb->range_end_ , lb->delegated_length_ );
109+ append (range, prefix);
110+
111+ // Everything is fine.
112+ return (true );
113+ }
114+
115115void
116116FreeLeaseQueue::append (const FreeLeaseQueue::Range& range, const IOAddress& address) {
117117 // Make sure the address is within the range boundaries.
118- if ((address < range.start_ ) || (range.end_ < address)) {
119- isc_throw (BadValue, " address " << address << " is not within the range of "
120- << range.start_ << " :" << range.end_ );
121- }
118+ checkRangeBoundaries (range, address);
122119 auto cont = getContainer (range);
123120 cont->insert (address);
124121}
125122
126123void
127- FreeLeaseQueue::append (const uint64_t range_index, const IOAddress& address ) {
124+ FreeLeaseQueue::append (const uint64_t range_index, const IOAddress& ip ) {
128125 auto desc = getContainerDescriptor (range_index);
129- if ((address < desc.range_start_ ) || (desc.range_end_ < address )) {
130- isc_throw (BadValue, " address " << address << " is not within the range of "
131- << desc. range_start_ << " :" << desc.range_end_ );
126+ if ((ip < desc.range_start_ ) || (desc.range_end_ < ip )) {
127+ isc_throw (BadValue, ip << " is not within the range of " << desc. range_start_
128+ << " :" << desc.range_end_ );
132129 }
133- desc.container_ ->insert (address);
130+ desc.container_ ->insert (ip);
131+ }
132+
133+ void
134+ FreeLeaseQueue::append (const FreeLeaseQueue::PrefixRange& range, const asiolink::IOAddress& prefix) {
135+ checkRangeBoundaries (range, prefix, true );
136+ auto cont = getContainer (range);
137+ cont->insert (prefix);
134138}
135139
136140bool
137141FreeLeaseQueue::use (const FreeLeaseQueue::Range& range, const IOAddress& address) {
138- if ((address < range.start_ ) || (range.end_ < address)) {
139- isc_throw (BadValue, " address " << address << " is outside of the range of "
140- << range.start_ << " :" << range.end_ );
141- }
142+ checkRangeBoundaries (range, address);
142143 auto cont = getContainer (range);
143144 auto found = cont->find (address);
144145 if (found != cont->end ()) {
@@ -148,28 +149,74 @@ FreeLeaseQueue::use(const FreeLeaseQueue::Range& range, const IOAddress& address
148149 return (false );
149150}
150151
151- IOAddress
152- FreeLeaseQueue::next (const FreeLeaseQueue::Range& range) {
153- return (popNextInternal (range, true ));
152+ bool
153+ FreeLeaseQueue::use (const FreeLeaseQueue::PrefixRange& range, const IOAddress& prefix) {
154+ checkRangeBoundaries (range, prefix, true );
155+ auto cont = getContainer (range);
156+ auto found = cont->find (prefix);
157+ if (found != cont->end ()) {
158+ static_cast <void >(cont->erase (found));
159+ return (true );
160+ }
161+ return (false );
154162}
155163
156- IOAddress
157- FreeLeaseQueue::pop (const FreeLeaseQueue::Range& range) {
158- return (popNextInternal (range, false ));
164+ template <typename RangeType>
165+ void
166+ FreeLeaseQueue::checkRangeBoundaries (const RangeType& range, const IOAddress& ip,
167+ const bool prefix) const {
168+ if ((ip < range.start_ ) || (range.end_ < ip)) {
169+ isc_throw (BadValue, (prefix ? " prefix " : " address " ) << ip << " is not within the range of "
170+ << range.start_ << " :" << range.end_ );
171+ }
159172}
160173
161- uint64_t
162- FreeLeaseQueue::getRangeIndex (const FreeLeaseQueue::Range& range) const {
163- auto cont = containers_.get <1 >().find (range.start_ );
164- if (cont == containers_.get <1 >().end ()) {
165- isc_throw (BadValue, " conatiner for the specified address range " << range.start_
166- << " :" << range.end_ << " does not exist" );
174+ void
175+ FreeLeaseQueue::checkRangeOverlaps (const IOAddress& start, const IOAddress& end) const {
176+ // Get the next range in the container relative to the start of the new
177+ // range. The upper_bound returns the range which starts after the start
178+ // of the new range.
179+ auto next_range = containers_.lower_bound (start);
180+ // Get the range the range that is before that one. It is also possible that
181+ // there is no previous range in which case we default to end().
182+ auto previous_range = containers_.end ();
183+ // If the next range is at the beginning of the container there is no
184+ // previous range.
185+ if (next_range != containers_.begin ()) {
186+ // This should work fine even if the next range is set to end(). We
187+ // will get the range that is one position before end() and that
188+ // should be the range that goes before the new one.
189+ auto it = next_range;
190+ --it;
191+ previous_range = it;
192+ }
193+
194+ // Now that we have next and previous ranges set we should check that the
195+ // new range we're adding does not overlap with them.
196+
197+ // If the previous range exists, let's check that the start of the new
198+ // range is neither within that range nor lower. Assuming that the ranges
199+ // are constructed such that the end must be greater or equal the start
200+ // it is sufficient to check that the start of the new range is not lower
201+ // or equal the end of the previous range.
202+ if ((previous_range != containers_.end ()) &&
203+ (start <= previous_range->range_end_ )) {
204+ isc_throw (BadValue, " new address range " << start << " :" << end
205+ << " overlaps with the existing range" );
206+ }
207+
208+ // If the next range exists, let's check that the end of the new range
209+ // is neither within that range nor higher.
210+ if ((next_range != containers_.end ()) &&
211+ (next_range->range_start_ <= end)) {
212+ isc_throw (BadValue, " new address range " << start << " :" << end
213+ << " overlaps with the existing range" );
167214 }
168- return (std::distance (containers_.get <2 >().begin (), containers_.project <2 >(cont)));
169215}
170216
217+
171218FreeLeaseQueue::ContainerPtr
172- FreeLeaseQueue::getContainer (const FreeLeaseQueue::Range& range) {
219+ FreeLeaseQueue::getContainer (const FreeLeaseQueue::Range& range) const {
173220 auto cont = containers_.find (range.start_ );
174221 if (cont == containers_.end ()) {
175222 isc_throw (BadValue, " conatiner for the specified address range " << range.start_
@@ -178,8 +225,19 @@ FreeLeaseQueue::getContainer(const FreeLeaseQueue::Range& range) {
178225 return (cont->container_ );
179226}
180227
228+ FreeLeaseQueue::ContainerPtr
229+ FreeLeaseQueue::getContainer (const FreeLeaseQueue::PrefixRange& range) const {
230+ auto cont = containers_.find (range.start_ );
231+ if (cont == containers_.end ()) {
232+ isc_throw (BadValue, " conatiner for the specified prefix " << range.start_
233+ << " and delegated length of " << static_cast <int >(range.delegated_length_ )
234+ << " does not exist" );
235+ }
236+ return (cont->container_ );
237+ }
238+
181239FreeLeaseQueue::ContainerDescriptor
182- FreeLeaseQueue::getContainerDescriptor (const uint64_t range_index) {
240+ FreeLeaseQueue::getContainerDescriptor (const uint64_t range_index) const {
183241 if (containers_.get <2 >().size () <= range_index) {
184242 isc_throw (BadValue, " conatiner for the specified range index " << range_index
185243 << " does not exist" );
@@ -188,21 +246,5 @@ FreeLeaseQueue::getContainerDescriptor(const uint64_t range_index) {
188246 return (cont);
189247}
190248
191- IOAddress
192- FreeLeaseQueue::popNextInternal (const Range& range, const bool push) {
193- auto cont = getContainer (range);
194- if (cont->empty ()) {
195- return (IOAddress::IPV4_ZERO_ADDRESS ());
196- }
197- auto & idx = cont->get <1 >();
198- auto next = idx.front ();
199- idx.pop_front ();
200- if (push) {
201- idx.push_back (next);
202- }
203- return (next);
204-
205- }
206-
207249} // end of namespace isc::dhcp
208250} // end of namespace isc
0 commit comments