Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Sebastian Schrader
Kea
Commits
cb5533a1
Commit
cb5533a1
authored
Feb 18, 2015
by
Marcin Siodelski
Browse files
[master] Merge branch 'trac3711'
Conflicts: src/lib/asiolink/io_address.h src/lib/asiolink/tests/io_address_unittest.cc
parents
c38e3c01
b811723e
Changes
15
Hide whitespace changes
Inline
Sidebyside
src/lib/asiolink/io_address.cc
View file @
cb5533a1
// Copyright (C) 2010
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2010
2012, 20142015
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ 131,5 +131,55 @@ operator<<(std::ostream& os, const IOAddress& address) {
return
(
os
);
}
IOAddress
IOAddress
::
subtract
(
const
IOAddress
&
a
,
const
IOAddress
&
b
)
{
if
(
a
.
getFamily
()
!=
b
.
getFamily
())
{
isc_throw
(
BadValue
,
"Both addresses have to be the same family"
);
}
if
(
a
.
isV4
())
{
// Subtracting v4 is easy. We have uint32_t operator.
return
(
IOAddress
(
static_cast
<
uint32_t
>
(
a
)

static_cast
<
uint32_t
>
(
b
)));
}
else
{
// v6 is more involved.
// Let's extract the raw data first.
vector
<
uint8_t
>
a_vec
=
a
.
toBytes
();
vector
<
uint8_t
>
b_vec
=
b
.
toBytes
();
// ... and prepare the result
vector
<
uint8_t
>
result
(
V6ADDRESS_LEN
,
0
);
// Carry is a boolean, but to avoid its frequent casting, let's
// use uint8_t. Also, some would prefer to call it borrow, but I prefer
// carry. Somewhat relevant discussion here:
// http://en.wikipedia.org/wiki/Carry_flag#Carry_flag_vs._Borrow_flag
uint8_t
carry
=
0
;
// Now perform subtraction with borrow.
for
(
int
i
=
a_vec
.
size
()

1
;
i
>=
0
;

i
)
{
result
[
i
]
=
a_vec
[
i
]

b_vec
[
i
]

carry
;
carry
=
(
a_vec
[
i
]
<
b_vec
[
i
]
+
carry
);
}
return
(
fromBytes
(
AF_INET6
,
&
result
[
0
]));
}
}
IOAddress
IOAddress
::
increase
(
const
IOAddress
&
addr
)
{
std
::
vector
<
uint8_t
>
packed
(
addr
.
toBytes
());
// Start increasing the least significant byte
for
(
int
i
=
packed
.
size
()

1
;
i
>=
0
;

i
)
{
// if we haven't overflowed (0xff > 0x0), than we are done
if
(
++
packed
[
i
]
!=
0
)
{
break
;
}
}
return
(
IOAddress
::
fromBytes
(
addr
.
getFamily
(),
&
packed
[
0
]));
}
}
// namespace asiolink
}
// namespace isc
src/lib/asiolink/io_address.h
View file @
cb5533a1
...
...
@@ 221,6 +221,47 @@ public:
return
(
nequals
(
other
));
}
/// @brief Subtracts one address from another (a  b)
///
/// Treats addresses as integers and subtracts them. For example:
/// 192.0.2.5  192.0.2.0 = 0.0.0.5
/// fe80::abcd  fe80:: = ::abcd
///
/// It is possible to subtract greater from lesser address, e.g.
/// 192.168.56.10  192.168.67.20, but please do understand that
/// the address space is a finite field in mathematical sense, so
/// you may end up with a result that is greater then any of the
/// addresses you specified. Also, subtraction is not commutative,
/// so a  b != b  a.
///
/// This operation is essential for calculating the number of
/// leases in a pool, where we need to calculate (max  min).
/// @throw BadValue if addresses are of different family
/// @param a address to be subtracted from
/// @param b address to be subtracted
/// @return IOAddress object that represents the difference
static
IOAddress
subtract
(
const
IOAddress
&
a
,
const
IOAddress
&
b
);
/// @brief Returns an address increased by one
///
/// This method works for both IPv4 and IPv6 addresses. For example,
/// increase 192.0.2.255 will become 192.0.3.0.
///
/// Address space is a finite field in the mathematical sense, so keep
/// in mind that the address space "loops". 255.255.255.255 increased
/// by one gives 0.0.0.0. The same is true for maximum value of IPv6
/// (all 1's) looping to ::.
///
/// @todo Determine if we have a usecase for increasing the address
/// by more than one. Increase by one is used in AllocEngine. This method
/// could take extra parameter that specifies the value by which the
/// address should be increased.
///
/// @param addr address to be increased
/// @return address increased by one
static
IOAddress
increase
(
const
IOAddress
&
addr
);
/// \brief Converts IPv4 address to uint32_t
///
/// Will throw BadValue exception if that is not IPv4
...
...
src/lib/asiolink/tests/io_address_unittest.cc
View file @
cb5533a1
// Copyright (C) 2011
,
2015 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2011
2012,2014
2015
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ 17,6 +17,7 @@
#include
<asiolink/io_error.h>
#include
<asiolink/io_address.h>
#include
<exceptions/exceptions.h>
#include
<algorithm>
#include
<cstring>
...
...
@@ 102,7 +103,7 @@ TEST(IOAddressTest, toBytesV6) {
const
char
*
V6STRING
=
"2001:db8:1::dead:beef"
;
uint8_t
V6
[]
=
{
0x20
,
0x01
,
0x0d
,
0xb8
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0xde
,
0xad
,
0xbe
,
0xef
0x00
,
0x00
,
0x00
,
0x00
,
0xde
,
0xad
,
0xbe
,
0xef
};
std
::
vector
<
uint8_t
>
actual
=
IOAddress
(
V6STRING
).
toBytes
();
...
...
@@ 223,3 +224,77 @@ TEST(IOAddressTest, staticAddresses) {
EXPECT_EQ
(
IOAddress
(
"255.255.255.255"
),
IOAddress
::
IPV4_BCAST_ADDRESS
());
EXPECT_EQ
(
IOAddress
(
"::"
),
IOAddress
::
IPV6_ZERO_ADDRESS
());
}
// Tests whether address subtraction works correctly.
TEST
(
IOAddressTest
,
subtract
)
{
IOAddress
addr1
(
"192.0.2.12"
);
IOAddress
addr2
(
"192.0.2.5"
);
IOAddress
addr3
(
"192.0.2.0"
);
IOAddress
addr4
(
"0.0.2.1"
);
IOAddress
any4
(
"0.0.0.0"
);
IOAddress
bcast
(
"255.255.255.255"
);
EXPECT_EQ
(
"0.0.0.7"
,
IOAddress
::
subtract
(
addr1
,
addr2
).
toText
());
EXPECT_EQ
(
"0.0.0.12"
,
IOAddress
::
subtract
(
addr1
,
addr3
).
toText
());
// Subtracting 0.0.0.0 is like subtracting 0.
EXPECT_EQ
(
"192.0.2.12"
,
IOAddress
::
subtract
(
addr1
,
any4
).
toText
());
EXPECT_EQ
(
"192.0.2.13"
,
IOAddress
::
subtract
(
addr1
,
bcast
).
toText
());
EXPECT_EQ
(
"191.255.255.255"
,
IOAddress
::
subtract
(
addr3
,
addr4
).
toText
());
// Let's check if we can subtract greater address from smaller.
// This will check if we can "loop"
EXPECT_EQ
(
"255.255.255.251"
,
IOAddress
::
subtract
(
addr3
,
addr2
).
toText
());
IOAddress
addr6
(
"fe80::abcd"
);
IOAddress
addr7
(
"fe80::"
);
IOAddress
addr8
(
"fe80::1234"
);
IOAddress
addr9
(
"2001:db8::face"
);
IOAddress
addr10
(
"2001:db8::ffff:ffff:ffff:ffff"
);
IOAddress
addr11
(
"::1"
);
IOAddress
any6
(
"::"
);
EXPECT_EQ
(
"::abcd"
,
IOAddress
::
subtract
(
addr6
,
addr7
).
toText
());
EXPECT_EQ
(
"::9999"
,
IOAddress
::
subtract
(
addr6
,
addr8
).
toText
());
EXPECT_EQ
(
"::ffff:ffff:ffff:531"
,
IOAddress
::
subtract
(
addr10
,
addr9
).
toText
());
// Subtract with borrow, extreme edition. Need to borrow one bit
// 112 times.
EXPECT_EQ
(
"fe7f:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
,
IOAddress
::
subtract
(
addr7
,
addr11
).
toText
());
// Now check if we can loop beyond :: (::  ::1 is a lot of F's)
EXPECT_EQ
(
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
,
IOAddress
::
subtract
(
any6
,
addr11
).
toText
());
// Subtracting :: is like subtracting 0.
EXPECT_EQ
(
"2001:db8::face"
,
IOAddress
::
subtract
(
addr9
,
any6
).
toText
());
// Let's check if we can subtract greater address from smaller.
// This will check if we can "loop"
EXPECT_EQ
(
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:edcc"
,
IOAddress
::
subtract
(
addr7
,
addr8
).
toText
());
// Interfamily relations are not allowed.
EXPECT_THROW
(
IOAddress
::
subtract
(
addr1
,
addr6
),
isc
::
BadValue
);
EXPECT_THROW
(
IOAddress
::
subtract
(
addr6
,
addr1
),
isc
::
BadValue
);
}
// Test checks whether an address can be increased.
TEST
(
IOAddressTest
,
increaseAddr
)
{
IOAddress
addr1
(
"192.0.2.12"
);
IOAddress
any4
(
"0.0.0.0"
);
IOAddress
bcast
(
"255.255.255.255"
);
IOAddress
addr6
(
"2001:db8::ffff:ffff:ffff:ffff"
);
IOAddress
addr11
(
"::1"
);
IOAddress
any6
(
"::"
);
IOAddress
the_last_one
(
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
);
EXPECT_EQ
(
"192.0.2.13"
,
IOAddress
::
increase
(
addr1
).
toText
());
EXPECT_EQ
(
"0.0.0.1"
,
IOAddress
::
increase
(
any4
).
toText
());
EXPECT_EQ
(
"0.0.0.0"
,
IOAddress
::
increase
(
bcast
).
toText
());
EXPECT_EQ
(
"2001:db8:0:1::"
,
IOAddress
::
increase
(
addr6
).
toText
());
EXPECT_EQ
(
"::2"
,
IOAddress
::
increase
(
addr11
).
toText
());
EXPECT_EQ
(
"::1"
,
IOAddress
::
increase
(
any6
).
toText
());
EXPECT_EQ
(
"::"
,
IOAddress
::
increase
(
the_last_one
).
toText
());
}
src/lib/dhcpsrv/addr_utilities.cc
View file @
cb5533a1
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012
,2015
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ 15,6 +15,8 @@
#include
<dhcpsrv/addr_utilities.h>
#include
<exceptions/exceptions.h>
#include
<vector>
#include
<limits>
#include
<string.h>
using
namespace
isc
;
...
...
@@ 205,5 +207,100 @@ isc::asiolink::IOAddress getNetmask4(uint8_t len) {
return
(
IOAddress
(
x
));
}
uint64_t
addrsInRange
(
const
isc
::
asiolink
::
IOAddress
&
min
,
const
isc
::
asiolink
::
IOAddress
&
max
)
{
if
(
min
.
getFamily
()
!=
max
.
getFamily
())
{
isc_throw
(
BadValue
,
"Both addresses have to be the same family"
);
}
if
(
max
<
min
)
{
isc_throw
(
BadValue
,
min
.
toText
()
<<
" must not be greater than "
<<
max
.
toText
());
}
if
(
min
.
isV4
())
{
// Let's explicitly cast last_ and first_ (IOAddress). This conversion is
// automatic, but let's explicitly cast it show that we moved to integer
// domain and addresses are now substractable.
uint64_t
max_numeric
=
static_cast
<
uint32_t
>
(
max
);
uint64_t
min_numeric
=
static_cast
<
uint32_t
>
(
min
);
// We can simply subtract the values. We need to increase the result
// by one, as both min and max are included in the range. So even if
// min == max, there's one address.
return
(
max_numeric

min_numeric
+
1
);
}
else
{
// Calculating the difference in v6 is more involved. Let's subtract
// one from the other. By subtracting min from max, we move the
// [a, b] range to the [0, (ba)] range. We don't care about the beginning
// of the new range (it's always zero). The upper bound now specifies
// the number of addresses minus one.
IOAddress
count
=
IOAddress
::
subtract
(
max
,
min
);
// There's one very special case. Someone is trying to check how many
// IPv6 addresses are in IPv6 address space. He called this method
// with ::, ffff:ffff:ffff:fffff:ffff:ffff:ffff:ffff. The diff is also
// all 1s. Had we increased it by one, the address would flip to all 0s.
// This will not happen in a real world. Apparently, unittests are
// sometimes nastier then a real world.
static
IOAddress
max6
(
"ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"
);
if
(
count
==
max6
)
{
return
(
std
::
numeric_limits
<
uint64_t
>::
max
());
}
// Increase it by one (a..a range still contains one address, even though
// a subtracted from a is zero).
count
=
IOAddress
::
increase
(
count
);
// We don't have uint128, so for anything greater than 2^64, we'll just
// assume numeric_limits<uint64_t>::max. Let's do it the manual way.
const
std
::
vector
<
uint8_t
>&
bin
(
count
.
toBytes
());
// If any of the most significant 64 bits is set, we have more than
// 2^64 addresses and can't represent it even on uint64_t.
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
if
(
bin
[
i
])
{
return
(
std
::
numeric_limits
<
uint64_t
>::
max
());
}
}
// Ok, we're good. The pool is sanely sized. It may be huge, but at least
// that's something we can represent on uint64_t.
uint64_t
numeric
=
0
;
for
(
int
i
=
8
;
i
<
16
;
i
++
)
{
numeric
<<=
8
;
numeric
+=
bin
[
i
];
}
return
(
numeric
);
}
}
uint64_t
prefixesInRange
(
const
uint8_t
pool_len
,
const
uint8_t
delegated_len
)
{
if
(
delegated_len
<
pool_len
)
{
return
(
0
);
}
uint64_t
count
=
delegated_len

pool_len
;
if
(
count
==
0
)
{
// If we want to delegate /64 out of /64 pool, we have only
// one prefix.
return
(
1
);
}
else
if
(
count
>=
64
)
{
// If the difference is greater than or equal 64, e.g. we want to
// delegate /96 out of /16 pool, the number is bigger than we can
// express, so we'll stick with maximum value of uint64_t.
return
(
std
::
numeric_limits
<
uint64_t
>::
max
());
}
else
{
// Now count specifies the exponent (e.g. if the difference between the
// delegated and pool length is 4, we have 16 prefixes), so we need
// to calculate 2^(count  1)
return
((
static_cast
<
uint64_t
>
(
2
))
<<
(
count

1
));
}
}
};
};
src/lib/dhcpsrv/addr_utilities.h
View file @
cb5533a1
// Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012
,20142015
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ 52,11 +52,37 @@ isc::asiolink::IOAddress firstAddrInPrefix(const isc::asiolink::IOAddress& prefi
isc
::
asiolink
::
IOAddress
lastAddrInPrefix
(
const
isc
::
asiolink
::
IOAddress
&
prefix
,
uint8_t
len
);
/// @brief
g
enerates an IPv4 netmask of specified length
/// @brief
G
enerates an IPv4 netmask of specified length
/// @throw BadValue if len is greater than 32
/// @return netmask
isc
::
asiolink
::
IOAddress
getNetmask4
(
uint8_t
len
);
/// @brief Returns number of available addresses in the specified range (min  max).
///
/// Note that for min equal max case, the number of addresses is one.
///
/// @throw BadValue if min and max are not of the same family (both must be
/// either IPv4 or IPv6) or if max < min.
///
/// @param min the first address in range
/// @param max the last address in range
/// @return number of addresses in range
uint64_t
addrsInRange
(
const
isc
::
asiolink
::
IOAddress
&
min
,
const
isc
::
asiolink
::
IOAddress
&
max
);
/// @brief Returns number of available IPv6 prefixes in the specified prefix.
///
/// Note that if the answer is bigger than uint64_t can hold, it will return
/// the max value of uint64_t type.
///
/// Example: prefixesInRange(48, 64) returns 65536, as there are /48 pool
/// can be split into 65536 prefixes, each /64 large.
///
/// @param pool_len length of the pool in bits
/// @param delegated_len length of the prefixes to be delegated from the pool
/// @return number of prefixes in range
uint64_t
prefixesInRange
(
const
uint8_t
pool_len
,
const
uint8_t
delegated_len
);
};
};
...
...
src/lib/dhcpsrv/alloc_engine.cc
View file @
cb5533a1
...
...
@@ 66,34 +66,6 @@ AllocEngine::IterativeAllocator::IterativeAllocator(Lease::Type lease_type)
:
Allocator
(
lease_type
)
{
}
isc
::
asiolink
::
IOAddress
AllocEngine
::
IterativeAllocator
::
increaseAddress
(
const
isc
::
asiolink
::
IOAddress
&
addr
)
{
// Get a buffer holding an address.
const
std
::
vector
<
uint8_t
>&
vec
=
addr
.
toBytes
();
// Get the address length.
const
int
len
=
vec
.
size
();
// Since the same array will be used to hold the IPv4 and IPv6
// address we have to make sure that the size of the array
// we allocate will work for both types of address.
BOOST_STATIC_ASSERT
(
V4ADDRESS_LEN
<=
V6ADDRESS_LEN
);
uint8_t
packed
[
V6ADDRESS_LEN
];
// Copy the address. It can be either V4 or V6.
std
::
memcpy
(
packed
,
&
vec
[
0
],
len
);
// Start increasing the least significant byte
for
(
int
i
=
len

1
;
i
>=
0
;

i
)
{
++
packed
[
i
];
// if we haven't overflowed (0xff > 0x0), than we are done
if
(
packed
[
i
]
!=
0
)
{
break
;
}
}
return
(
IOAddress
::
fromBytes
(
addr
.
getFamily
(),
packed
));
}
isc
::
asiolink
::
IOAddress
AllocEngine
::
IterativeAllocator
::
increasePrefix
(
const
isc
::
asiolink
::
IOAddress
&
prefix
,
const
uint8_t
prefix_len
)
{
...
...
@@ 193,7 +165,7 @@ AllocEngine::IterativeAllocator::pickAddress(const SubnetPtr& subnet,
IOAddress
next
(
"::"
);
if
(
!
prefix
)
{
next
=
increase
Address
(
last
);
// basically addr++
next
=
IOAddress
::
increase
(
last
);
// basically addr++
}
else
{
Pool6Ptr
pool6
=
boost
::
dynamic_pointer_cast
<
Pool6
>
(
*
it
);
if
(
!
pool6
)
{
...
...
@@ 566,21 +538,12 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
//  we find an address for which the lease has expired
//  we exhaust number of tries
//
// @todo: Current code does not handle pool exhaustion well. It will be
// improved. Current problems:
// 1. with attempts set to too large value (e.g. 1000) and a small pool (e.g.
// 10 addresses), we will iterate over it 100 times before giving up
// 2. attempts 0 mean unlimited (this is really UINT_MAX, not infinite)
// 3. the whole concept of infinite attempts is just asking for infinite loop
// We may consider some form or reference counting (this pool has X addresses
// left), but this has one major problem. We exactly control allocation
// moment, but we currently do not control expiration time at all
// Initialize the maximum number of attempts to pick and allocate an
// address. The value of 0 means "infinite", which is maximum uint32_t
// value.
uint32_t
max_attempts
=
(
attempts_
==
0
)
?
std
::
numeric_limits
<
uint32_t
>::
max
()
:
attempts_
;
/// @todo: We used to use hardcoded number of attempts (100). Now we dynamically
/// calculate the number of possible leases in all pools in this subnet and
/// try that number of times at most. It would be useful to that value if
/// attempts_, specified by the user could override that value (and keep
/// dynamic if they're set to 0).
uint32_t
max_attempts
=
ctx
.
subnet_
>
getPoolCapacity
(
ctx
.
type_
);
for
(
uint32_t
i
=
0
;
i
<
max_attempts
;
++
i
)
{
IOAddress
candidate
=
allocator
>
pickAddress
(
ctx
.
subnet_
,
ctx
.
duid_
,
hint
);
...
...
@@ 1039,16 +1002,12 @@ AllocEngine::allocateLease4(const SubnetPtr& subnet, const ClientIdPtr& clientid
//  we find an address for which the lease has expired
//  we exhaust the number of tries
//
/// @todo: Current code does not handle pool exhaustion well. It will be
/// improved. Current problems:
/// 1. with attempts set to too large value (e.g. 1000) and a small pool (e.g.
/// 10 addresses), we will iterate over it 100 times before giving up
/// 2. attempts 0 mean unlimited (this is really UINT_MAX, not infinite)
/// 3. the whole concept of infinite attempts is just asking for infinite loop
/// We may consider some form or reference counting (this pool has X addresses
/// left), but this has one major problem. We exactly control allocation
/// moment, but we currently do not control expiration time at all
unsigned
int
i
=
attempts_
;
/// @todo: We used to use hardcoded number of attempts (100). Now we dynamically
/// calculate the number of possible leases in all pools in this subnet and
/// try that number of times at most. It would be useful to that value if
/// attempts_, specified by the user could override that value (and keep
/// dynamic if they're set to 0).
uint64_t
i
=
subnet
>
getPoolCapacity
(
Lease
::
TYPE_V4
);
do
{
// Decrease the number of remaining attempts here so as we guarantee
// that it is decreased when the code below uses "continue".
...
...
src/lib/dhcpsrv/alloc_engine.h
View file @
cb5533a1
...
...
@@ 137,16 +137,6 @@ protected:
const
isc
::
asiolink
::
IOAddress
&
hint
);
protected:
/// @brief Returns an address increased by one
///
/// This method works for both IPv4 and IPv6 addresses. For example,
/// increase 192.0.2.255 will become 192.0.3.0.
///
/// @param addr address to be increased
/// @return address increased by one
static
isc
::
asiolink
::
IOAddress
increaseAddress
(
const
isc
::
asiolink
::
IOAddress
&
addr
);
/// @brief Returns the next prefix
///
/// This method works for IPv6 addresses only. It increases
...
...
src/lib/dhcpsrv/pool.cc
View file @
cb5533a1
// Copyright (C) 2012201
3
Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 2012201
5
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ 24,7 +24,8 @@ namespace dhcp {
Pool
::
Pool
(
Lease
::
Type
type
,
const
isc
::
asiolink
::
IOAddress
&
first
,
const
isc
::
asiolink
::
IOAddress
&
last
)
:
id_
(
getNextID
()),
first_
(
first
),
last_
(
last
),
type_
(
type
)
{
:
id_
(
getNextID
()),
first_
(
first
),
last_
(
last
),
type_
(
type
),
capacity_
(
0
)
{
}
bool
Pool
::
inRange
(
const
isc
::
asiolink
::
IOAddress
&
addr
)
const
{
...
...
@@ 50,6 +51,12 @@ Pool4::Pool4(const isc::asiolink::IOAddress& first,
if
(
last
<
first
)
{
isc_throw
(
BadValue
,
"Upper boundary is smaller than lower boundary."
);
}
// This is IPv4 pool, which only has one type. We can calculate
// the number of theoretically possible leases in it. As there's 2^32
// possible IPv4 addresses, we'll be able to accurately store that
// info.
capacity_
=
addrsInRange
(
first
,
last
);
}
Pool4
::
Pool4
(
const
isc
::
asiolink
::
IOAddress
&
prefix
,
uint8_t
prefix_len
)
...
...
@@ 67,8 +74,13 @@ Pool4::Pool4( const isc::asiolink::IOAddress& prefix, uint8_t prefix_len)
// Let's now calculate the last address in defined pool
last_
=
lastAddrInPrefix
(
prefix
,
prefix_len
);
}
// This is IPv4 pool, which only has one type. We can calculate
// the number of theoretically possible leases in it. As there's 2^32
// possible IPv4 addresses, we'll be able to accurately store that
// info.
capacity_
=
addrsInRange
(
prefix
,
last_
);
}
Pool6
::
Pool6
(
Lease
::
Type
type
,
const
isc
::
asiolink
::
IOAddress
&
first
,
const
isc
::
asiolink
::
IOAddress
&
last
)
...
...
@@ 105,6 +117,11 @@ Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& first,
isc_throw
(
BadValue
,
"Invalid Pool6 type specified:"
<<
static_cast
<
int
>
(
type
));
}
// Let's calculate the theoretical number of leases in this pool.
// If the pool is extremely large (i.e. contains more than 2^64 addresses,
// we'll just cap it at max value of uint64_t).
capacity_
=
addrsInRange
(
first
,
last
);
}
Pool6
::
Pool6
(
Lease
::
Type
type
,
const
isc
::
asiolink
::
IOAddress
&
prefix
,
...
...
@@ 123,7 +140,7 @@ Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& prefix,
if
(
prefix_len
>
delegated_len
)
{
isc_throw
(
BadValue
,
"Delegated length ("
<<
static_cast
<
int
>
(
delegated_len
)
<<
") must be longer than prefix length ("
<<
") must be longer than
or equal to
prefix length ("
<<
static_cast
<
int
>
(
prefix_len
)
<<
")"
);
}
...
...
@@ 138,6 +155,11 @@ Pool6::Pool6(Lease::Type type, const isc::asiolink::IOAddress& prefix,
// Let's now calculate the last address in defined pool
last_
=
lastAddrInPrefix
(
prefix
,
prefix_len
);
// Let's calculate the theoretical number of leases in this pool.
// For addresses, we could use addrsInRange(prefix, last_), but it's
// much faster to do calculations on prefix lengths.
capacity_
=
prefixesInRange
(
prefix_len
,
delegated_len
);
}
std
::
string
...
...
@@ 149,6 +171,5 @@ Pool6::toText() const {
return
(
tmp
.
str
());
}
};
// end of isc::dhcp namespace
};
// end of isc namespace
src/lib/dhcpsrv/pool.h
View file @
cb5533a1
// Copyright (C) 20122013 Internet Systems Consortium, Inc. ("ISC")
// Copyright (C) 20122013
,2015
Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
...
...
@@ 79,6 +79,14 @@ public:
virtual
~
Pool
()
{
}
/// @brief Returns the number of all leases in this pool.
///
/// Note that this is the upper bound, assuming that no leases are used
/// and there are no host reservations. This is just a theoretical calculation.
/// @return number of possible leases in this pool
uint64_t
getCapacity
()
const
{
return
(
capacity_
);
}
protected:
/// @brief protected constructor
...
...
@@ 120,6 +128,14 @@ protected:
/// @brief defines a lease type that will be served from this pool
Lease
::
Type
type_
;
/// @brief Stores number of possible leases.
///
/// This could be calculated on the fly, but the calculations are somewhat
/// involved, so it is more efficient to calculate it once and just store
/// the result. Note that for very large pools, the number is capped at
/// max value of uint64_t.
uint64_t
capacity_
;
};
/// @brief Pool information for IPv4 addresses
...
...
src/lib/dhcpsrv/subnet.cc
View file @
cb5533a1
...
...
@@ 132,6 +132,40 @@ Subnet::toText() const {
return
(
tmp
.
str
());
}
uint64_t
Subnet
::
getPoolCapacity
(
Lease
::
Type
type
)
const
{
switch
(
type
)
{
case
Lease
::
TYPE_V4
:
case
Lease
::
TYPE_NA
:
return
sumPoolCapacity
(
pools_
);
case
Lease
::
TYPE_TA
:
return
sumPoolCapacity
(
pools_ta_
);
case
Lease
::
TYPE_PD
:
return
sumPoolCapacity
(
pools_pd_
);
default:
isc_throw
(
BadValue
,
"Unsupported pool type: "