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
ISC Open Source Projects
Kea
Commits
113fef86
Commit
113fef86
authored
Dec 13, 2013
by
Tomek Mrugalski
🛰
Browse files
[2246] Merge branch 'master' into trac2246 (includes
#1824
fix)
Conflicts: ChangeLog
parents
e5ee6e78
39e902dc
Changes
18
Expand all
Hide whitespace changes
Inline
Side-by-side
ChangeLog
View file @
113fef86
...
...
@@ -4,6 +4,25 @@
contributing a patch.
(Trac #2246, git abcd)
717. [bug] marcin
Fixed the bug which incorrectly treated DHCPv4 option codes 224-254 as
standard options, barring them from being used as custom options.
(Trac #2772, git c6158690c389d75686545459618ae0bf16f2cdb8)
716. [func] marcin
perfdhcp: added support for sending DHCPv6 Relese messages at the specified
rate and measure performance. The orphan messages counters are not
displayed for individual exchanges anymore. The following ticket: #3261
has been submitted to implement global orphan counting for all exchange
types.
(Trac #3181, git 684524bc130080e4fa31b65edfd14d58eec37e50)
715. [bug] marcin
libdhcp++: Used the CMSG_SPACE instead of CMSG_LEN macro to calculate
msg_controllen field of the DHCPv6 message. Use of CMSG_LEN causes
sendmsg failures on OpenBSD due to the bug kernel/6080 on OpenBSD.
(Trac #1824, git 39c9499d001a98c8d2f5792563c28a5eb2cc5fcb)
714. [doc] tomek
BIND10 Contributor's Guide added.
(Trac #3109, git 016bfae00460b4f88adbfd07ed26759eb294ef10)
...
...
@@ -13,7 +32,7 @@
b10-dhcp-ddns. The class now generates all DNS update request variations
needed to fulfill it's state machine in compliance with RFC 4703, sections
5.3 and 5.4.
(Trac# 32
07
, git dceca9554cb9410dd8d12371b68198b797cb6cfb)
(Trac# 32
41
, git dceca9554cb9410dd8d12371b68198b797cb6cfb)
712. [func] marcin,dclink
b10-dhcp4: If server fails to open a socket on one interface it
...
...
@@ -30,7 +49,7 @@
reverse DNS entries for a given FQDN. It does not yet construct
the actual DNS update requests, this will be added under Trac#
3241.
(Trac# 3
2
07, git 8f99da735a9f39d514c40d0a295f751dc8edfbcd)
(Trac# 30
8
7, git 8f99da735a9f39d514c40d0a295f751dc8edfbcd)
710. [build] jinmei
Fixed various build time issues for MacOS X 10.9. Those include
...
...
src/lib/dhcp/iface_mgr.cc
View file @
113fef86
...
...
@@ -26,7 +26,8 @@
#include
<exceptions/exceptions.h>
#include
<util/io/pktinfo_utilities.h>
#include
<cstring>
#include
<errno.h>
#include
<fstream>
#include
<sstream>
...
...
@@ -892,13 +893,22 @@ IfaceMgr::send(const Pkt6Ptr& pkt) {
struct
in6_pktinfo
*
pktinfo
=
convertPktInfo6
(
CMSG_DATA
(
cmsg
));
memset
(
pktinfo
,
0
,
sizeof
(
struct
in6_pktinfo
));
pktinfo
->
ipi6_ifindex
=
pkt
->
getIndex
();
m
.
msg_controllen
=
cmsg
->
cmsg_len
;
// According to RFC3542, section 20.2, the msg_controllen field
// may be set using CMSG_SPACE (which includes padding) or
// using CMSG_LEN. Both forms appear to work fine on Linux, FreeBSD,
// NetBSD, but OpenBSD appears to have a bug, discussed here:
// http://www.archivum.info/mailing.openbsd.bugs/2009-02/00017/
// kernel-6080-msg_controllen-of-IPV6_PKTINFO.html
// which causes sendmsg to return EINVAL if the CMSG_LEN is
// used to set the msg_controllen value.
m
.
msg_controllen
=
CMSG_SPACE
(
sizeof
(
struct
in6_pktinfo
));
pkt
->
updateTimestamp
();
result
=
sendmsg
(
getSocket
(
*
pkt
),
&
m
,
0
);
if
(
result
<
0
)
{
isc_throw
(
SocketWriteError
,
"Pkt6 send failed: sendmsg() returned "
<<
result
);
isc_throw
(
SocketWriteError
,
"pkt6 send failed: sendmsg() returned"
" with an error: "
<<
strerror
(
errno
));
}
return
(
result
);
...
...
src/lib/dhcp/libdhcp++.cc
View file @
113fef86
...
...
@@ -163,9 +163,9 @@ LibDHCP::isStandardOption(const Option::Universe u, const uint16_t code) {
code
==
126
||
code
==
127
||
(
code
>
146
&&
code
<
150
)
||
(
code
>
177
&&
code
<
208
)
||
(
code
>
177
&&
code
<
208
)
||
(
code
>
213
&&
code
<
220
)
||
(
code
>
221
&&
code
<
2
24
)))
{
(
code
>
221
&&
code
<
2
55
)))
{
return
(
true
);
}
...
...
src/lib/dhcp/pkt_filter_inet.cc
View file @
113fef86
...
...
@@ -16,6 +16,8 @@
#include
<dhcp/iface_mgr.h>
#include
<dhcp/pkt4.h>
#include
<dhcp/pkt_filter_inet.h>
#include
<errno.h>
#include
<cstring>
using
namespace
isc
::
asiolink
;
...
...
@@ -235,14 +237,15 @@ PktFilterInet::send(const Iface&, uint16_t sockfd,
struct
in_pktinfo
*
pktinfo
=
(
struct
in_pktinfo
*
)
CMSG_DATA
(
cmsg
);
memset
(
pktinfo
,
0
,
sizeof
(
struct
in_pktinfo
));
pktinfo
->
ipi_ifindex
=
pkt
->
getIndex
();
m
.
msg_controllen
=
cmsg
->
cmsg_len
;
m
.
msg_controllen
=
CMSG_SPACE
(
sizeof
(
struct
in_pktinfo
))
;
#endif
pkt
->
updateTimestamp
();
int
result
=
sendmsg
(
sockfd
,
&
m
,
0
);
if
(
result
<
0
)
{
isc_throw
(
SocketWriteError
,
"pkt4 send failed"
);
isc_throw
(
SocketWriteError
,
"pkt4 send failed: sendmsg() returned "
" with an error: "
<<
strerror
(
errno
));
}
return
(
result
);
...
...
src/lib/dhcp/tests/libdhcp++_unittest.cc
View file @
113fef86
...
...
@@ -643,7 +643,10 @@ TEST_F(LibDhcpTest, isStandardOption4) {
187
,
188
,
189
,
190
,
191
,
192
,
193
,
194
,
195
,
196
,
197
,
198
,
199
,
200
,
201
,
202
,
203
,
204
,
205
,
206
,
207
,
214
,
215
,
216
,
217
,
218
,
219
,
222
,
223
};
222
,
223
,
224
,
225
,
226
,
227
,
228
,
229
,
230
,
231
,
232
,
233
,
234
,
235
,
236
,
237
,
238
,
239
,
240
,
241
,
242
,
243
,
244
,
245
,
246
,
247
,
248
,
249
,
250
,
251
,
252
,
253
,
254
};
const
size_t
unassigned_num
=
sizeof
(
unassigned_codes
)
/
sizeof
(
unassigned_codes
[
0
]);
// Try all possible option codes.
...
...
tests/tools/perfdhcp/Makefile.am
View file @
113fef86
...
...
@@ -25,6 +25,7 @@ perfdhcp_SOURCES += perf_pkt6.cc perf_pkt6.h
perfdhcp_SOURCES
+=
perf_pkt4.cc perf_pkt4.h
perfdhcp_SOURCES
+=
packet_storage.h
perfdhcp_SOURCES
+=
pkt_transform.cc pkt_transform.h
perfdhcp_SOURCES
+=
rate_control.cc rate_control.h
perfdhcp_SOURCES
+=
stats_mgr.h
perfdhcp_SOURCES
+=
test_control.cc test_control.h
libb10_perfdhcp___la_CXXFLAGS
=
$(AM_CXXFLAGS)
...
...
tests/tools/perfdhcp/command_options.cc
View file @
113fef86
...
...
@@ -114,6 +114,7 @@ CommandOptions::reset() {
lease_type_
.
set
(
LeaseType
::
ADDRESS
);
rate_
=
0
;
renew_rate_
=
0
;
release_rate_
=
0
;
report_delay_
=
0
;
clients_num_
=
0
;
mac_template_
.
assign
(
mac
,
mac
+
6
);
...
...
@@ -211,7 +212,7 @@ CommandOptions::initialize(int argc, char** argv, bool print_cmd_line) {
// In this section we collect argument values from command line
// they will be tuned and validated elsewhere
while
((
opt
=
getopt
(
argc
,
argv
,
"hv46r:t:R:b:n:p:d:D:l:P:a:L:"
"s:iBc1T:X:O:E:S:I:x:w:e:f:"
))
!=
-
1
)
{
"s:iBc1T:X:O:E:S:I:x:w:e:f:
F:
"
))
!=
-
1
)
{
stream
<<
" -"
<<
static_cast
<
char
>
(
opt
);
if
(
optarg
)
{
stream
<<
" "
<<
optarg
;
...
...
@@ -307,6 +308,12 @@ CommandOptions::initialize(int argc, char** argv, bool print_cmd_line) {
" must be a positive integer"
);
break
;
case
'F'
:
release_rate_
=
positiveInteger
(
"value of the release rate:"
" -F<release-rate> must be a"
" positive integer"
);
break
;
case
'h'
:
usage
();
return
(
true
);
...
...
@@ -690,6 +697,8 @@ CommandOptions::validate() const {
"-6 (IPv6) must be set to use -c"
);
check
((
getIpVersion
()
!=
6
)
&&
(
getRenewRate
()
!=
0
),
"-f<renew-rate> may be used with -6 (IPv6) only"
);
check
((
getIpVersion
()
!=
6
)
&&
(
getReleaseRate
()
!=
0
),
"-F<release-rate> may be used with -6 (IPv6) only"
);
check
((
getExchangeMode
()
==
DO_SA
)
&&
(
getNumRequests
().
size
()
>
1
),
"second -n<num-request> is not compatible with -i"
);
check
((
getIpVersion
()
==
4
)
&&
!
getLeaseType
().
is
(
LeaseType
::
ADDRESS
),
...
...
@@ -719,6 +728,8 @@ CommandOptions::validate() const {
"-I<ip-offset> is not compatible with -i"
);
check
((
getExchangeMode
()
==
DO_SA
)
&&
(
getRenewRate
()
!=
0
),
"-f<renew-rate> is not compatible with -i"
);
check
((
getExchangeMode
()
==
DO_SA
)
&&
(
getReleaseRate
()
!=
0
),
"-F<release-rate> is not compatible with -i"
);
check
((
getExchangeMode
()
!=
DO_SA
)
&&
(
isRapidCommit
()
!=
0
),
"-i must be set to use -c"
);
check
((
getRate
()
==
0
)
&&
(
getReportDelay
()
!=
0
),
...
...
@@ -730,12 +741,16 @@ CommandOptions::validate() const {
check
((
getRate
()
==
0
)
&&
((
getMaxDrop
().
size
()
>
0
)
||
getMaxDropPercentage
().
size
()
>
0
),
"-r<rate> must be set to use -D<max-drop>"
);
check
((
getRate
()
!=
0
)
&&
(
getRenewRate
()
>
getRate
()),
"Renew rate specified as -f<renew-rate> must not be greater than"
" the rate specified as -r<rate>"
);
check
((
getRate
()
!=
0
)
&&
(
getRenewRate
()
+
getReleaseRate
()
>
getRate
()),
"The sum of Renew rate (-f<renew-rate>) and Release rate"
" (-F<release-rate>) must not be greater than the exchange"
" rate specified as -r<rate>"
);
check
((
getRate
()
==
0
)
&&
(
getRenewRate
()
!=
0
),
"Renew rate specified as -f<renew-rate> must not be specified"
" when -r<rate> parameter is not specified"
);
check
((
getRate
()
==
0
)
&&
(
getReleaseRate
()
!=
0
),
"Release rate specified as -F<release-rate> must not be specified"
" when -r<rate> parameter is not specified"
);
check
((
getTemplateFiles
().
size
()
<
getTransactionIdOffset
().
size
()),
"-T<template-file> must be set to use -X<xid-offset>"
);
check
((
getTemplateFiles
().
size
()
<
getRandomOffset
().
size
()),
...
...
@@ -816,6 +831,9 @@ CommandOptions::printCommandLine() const {
if
(
getRenewRate
()
!=
0
)
{
std
::
cout
<<
"renew-rate[1/s]="
<<
getRenewRate
()
<<
std
::
endl
;
}
if
(
getReleaseRate
()
!=
0
)
{
std
::
cout
<<
"release-rate[1/s]="
<<
getReleaseRate
()
<<
std
::
endl
;
}
if
(
report_delay_
!=
0
)
{
std
::
cout
<<
"report[s]="
<<
report_delay_
<<
std
::
endl
;
}
...
...
@@ -899,13 +917,14 @@ void
CommandOptions
::
usage
()
const
{
std
::
cout
<<
"perfdhcp [-hv] [-4|-6] [-e<lease-type>] [-r<rate>] [-f<renew-rate>]
\n
"
" [-t<report>] [-R<range>] [-b<base>] [-n<num-request>]
\n
"
" [-p<test-period>] [-d<drop-time>] [-D<max-drop>]
\n
"
" [-l<local-addr|interface>] [-P<preload>] [-a<aggressivity>]
\n
"
" [-L<local-port>] [-s<seed>] [-i] [-B] [-c] [-1]
\n
"
" [-T<template-file>] [-X<xid-offset>] [-O<random-offset]
\n
"
" [-E<time-offset>] [-S<srvid-offset>] [-I<ip-offset>]
\n
"
" [-x<diagnostic-selector>] [-w<wrapped>] [server]
\n
"
" [-F<release-rate>] [-t<report>] [-R<range>] [-b<base>]
\n
"
" [-n<num-request>] [-p<test-period>] [-d<drop-time>]
\n
"
" [-D<max-drop>] [-l<local-addr|interface>] [-P<preload>]
\n
"
" [-a<aggressivity>] [-L<local-port>] [-s<seed>] [-i] [-B]
\n
"
" [-c] [-1] [-T<template-file>] [-X<xid-offset>]
\n
"
" [-O<random-offset] [-E<time-offset>] [-S<srvid-offset>]
\n
"
" [-I<ip-offset>] [-x<diagnostic-selector>] [-w<wrapped>]
\n
"
" [server]
\n
"
"
\n
"
"The [server] argument is the name/address of the DHCP server to
\n
"
"contact. For DHCPv4 operation, exchanges are initiated by
\n
"
...
...
@@ -948,10 +967,6 @@ CommandOptions::usage() const {
"-E<time-offset>: Offset of the (DHCPv4) secs field / (DHCPv6)
\n
"
" elapsed-time option in the (second/request) template.
\n
"
" The value 0 disables it.
\n
"
"-f<renew-rate>: A rate at which IPv6 Renew requests are sent to
\n
"
" a server. This value must not be equal or lower than the rate
\n
"
" specified as -r<rate>. If -r<rate> is not specified, this
\n
"
" parameter must not be specified too.
\n
"
"-h: Print this help.
\n
"
"-i: Do only the initial part of an exchange: DO or SA, depending on
\n
"
" whether -6 is given.
\n
"
...
...
@@ -999,6 +1014,16 @@ CommandOptions::usage() const {
"
\n
"
"DHCPv6 only options:
\n
"
"-c: Add a rapid commit option (exchanges will be SA).
\n
"
"-f<renew-rate>: Rate at which IPv6 Renew requests are sent to
\n
"
" a server. This value is only valid when used in conjunction with
\n
"
" the exchange rate (given by -r<rate>). Furthermore the sum of
\n
"
" this value and the release-rate (given by -F<rate) must be equal
\n
"
" to or less than the exchange rate.
\n
"
"-F<release-rate>: Rate at which IPv6 Release requests are sent to
\n
"
" a server. This value is only valid when used in conjunction with
\n
"
" the exchange rate (given by -r<rate>). Furthermore the sum of
\n
"
" this value and the renew-rate (given by -f<rate) must be equal
\n
"
" to or less than the exchange rate.
\n
"
"
\n
"
"The remaining options are used only in conjunction with -r:
\n
"
"
\n
"
...
...
tests/tools/perfdhcp/command_options.h
View file @
113fef86
// Copyright (C) 2012-2013 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
...
...
@@ -156,11 +155,16 @@ public:
/// \return exchange rate per second.
int
getRate
()
const
{
return
rate_
;
}
/// \brief Returns a rate at which
I
Pv6 Renew messages are sent.
/// \brief Returns a rate at which
DHC
Pv6 Renew messages are sent.
///
/// \return A rate at which IPv6 Renew messages are sent.
int
getRenewRate
()
const
{
return
(
renew_rate_
);
}
/// \brief Returns a rate at which DHCPv6 Release messages are sent.
///
/// \return A rate at which DHCPv6 Release messages are sent.
int
getReleaseRate
()
const
{
return
(
release_rate_
);
}
/// \brief Returns delay between two performance reports.
///
/// \return delay between two consecutive performance reports.
...
...
@@ -469,6 +473,8 @@ private:
int
rate_
;
/// A rate at which DHCPv6 Renew messages are sent.
int
renew_rate_
;
/// A rate at which DHCPv6 Release messages are sent.
int
release_rate_
;
/// Delay between generation of two consecutive
/// performance reports
int
report_delay_
;
...
...
tests/tools/perfdhcp/rate_control.cc
0 → 100644
View file @
113fef86
// Copyright (C) 2013 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
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#include
<exceptions/exceptions.h>
#include
<tests/tools/perfdhcp/rate_control.h>
namespace
isc
{
namespace
perfdhcp
{
using
namespace
boost
::
posix_time
;
RateControl
::
RateControl
()
:
send_due_
(
currentTime
()),
last_sent_
(
currentTime
()),
aggressivity_
(
1
),
rate_
(
0
),
late_sent_
(
false
)
{
}
RateControl
::
RateControl
(
const
int
rate
,
const
int
aggressivity
)
:
send_due_
(
currentTime
()),
last_sent_
(
currentTime
()),
aggressivity_
(
aggressivity
),
rate_
(
rate
),
late_sent_
(
false
)
{
if
(
aggressivity_
<
1
)
{
isc_throw
(
isc
::
BadValue
,
"invalid value of aggressivity "
<<
aggressivity
<<
", expected value is greater than 0"
);
}
if
(
rate_
<
0
)
{
isc_throw
(
isc
::
BadValue
,
"invalid value of rate "
<<
rate
<<
", expected non-negative value"
);
}
}
uint64_t
RateControl
::
getOutboundMessageCount
()
{
// We need calculate the due time for sending next set of messages.
updateSendDue
();
// Get current time. If we are behind due time, we have to calculate
// how many messages to send to catch up with the rate.
ptime
now
=
currentTime
();
if
(
now
>=
send_due_
)
{
// Reset number of exchanges.
uint64_t
due_exchanges
=
0
;
// If rate is specified from the command line we have to
// synchornize with it.
if
(
getRate
()
!=
0
)
{
time_period
period
(
send_due_
,
now
);
time_duration
duration
=
period
.
length
();
// due_factor indicates the number of seconds that
// sending next chunk of packets will take.
double
due_factor
=
duration
.
fractional_seconds
()
/
time_duration
::
ticks_per_second
();
due_factor
+=
duration
.
total_seconds
();
// Multiplying due_factor by expected rate gives the number
// of exchanges to be initiated.
due_exchanges
=
static_cast
<
uint64_t
>
(
due_factor
*
getRate
());
// We want to make sure that at least one packet goes out.
if
(
due_exchanges
==
0
)
{
due_exchanges
=
1
;
}
// We should not exceed aggressivity as it could have been
// restricted from command line.
if
(
due_exchanges
>
getAggressivity
())
{
due_exchanges
=
getAggressivity
();
}
}
else
{
// Rate is not specified so we rely on aggressivity
// which is the number of packets to be sent in
// one chunk.
due_exchanges
=
getAggressivity
();
}
return
(
due_exchanges
);
}
return
(
0
);
}
boost
::
posix_time
::
ptime
RateControl
::
currentTime
()
{
return
(
microsec_clock
::
universal_time
());
}
void
RateControl
::
updateSendDue
()
{
// There is no sense to update due time if the current due time is in the
// future. The due time is calculated as a duration between the moment
// when the last message of the given type was sent and the time when
// next one is supposed to be sent based on a given rate. The former value
// will not change until we send the next message, which we don't do
// until we reach the due time.
if
(
send_due_
>
currentTime
())
{
return
;
}
// This is initialized in the class constructor, so if it is not initialized
// it is a programmatic error.
if
(
last_sent_
.
is_not_a_date_time
())
{
isc_throw
(
isc
::
Unexpected
,
"timestamp of the last sent packet not"
" initialized"
);
}
// If rate was not specified we will wait just one clock tick to
// send next packet. This simulates best effort conditions.
long
duration
=
1
;
if
(
getRate
()
!=
0
)
{
// We use number of ticks instead of nanoseconds because
// nanosecond resolution may not be available on some
// machines. Number of ticks guarantees the highest possible
// timer resolution.
duration
=
time_duration
::
ticks_per_second
()
/
getRate
();
}
// Calculate due time to initiate next chunk of exchanges.
send_due_
=
last_sent_
+
time_duration
(
0
,
0
,
0
,
duration
);
if
(
send_due_
>
currentTime
())
{
late_sent_
=
true
;
}
else
{
late_sent_
=
false
;
}
}
void
RateControl
::
setAggressivity
(
const
int
aggressivity
)
{
if
(
aggressivity
<
1
)
{
isc_throw
(
isc
::
BadValue
,
"invalid value of aggressivity "
<<
aggressivity
<<
", expected value is greater than 0"
);
}
aggressivity_
=
aggressivity
;
}
void
RateControl
::
setRate
(
const
int
rate
)
{
if
(
rate
<
0
)
{
isc_throw
(
isc
::
BadValue
,
"invalid value of rate "
<<
rate
<<
", expected non-negative value"
);
}
rate_
=
rate
;
}
void
RateControl
::
setRelativeDue
(
const
int
offset
)
{
send_due_
=
offset
>
0
?
currentTime
()
+
seconds
(
abs
(
offset
))
:
currentTime
()
-
seconds
(
abs
(
offset
));
}
void
RateControl
::
updateSendTime
()
{
last_sent_
=
currentTime
();
}
}
// namespace perfdhcp
}
// namespace isc
tests/tools/perfdhcp/rate_control.h
0 → 100644
View file @
113fef86
// Copyright (C) 2013 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
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
#ifndef RATE_CONTROL_H
#define RATE_CONTROL_H
#include
<boost/date_time/posix_time/posix_time.hpp>
namespace
isc
{
namespace
perfdhcp
{
/// \brief A message sending rate control class for perfdhcp.
///
/// This class provides the means to control the rate at which messages
/// of the specific type are sent by perfdhcp. Each message type,
/// for which the desired rate can be specified, has a corresponding
/// \c RateControl object. So, the perfdhcp is using up to three objects
/// of this type at the same time, to control the rate of the following
/// messages being sent:
/// - Discover(DHCPv4) or Solicit (DHCPv6)
/// - Renew (DHCPv6) or Request (DHCPv4) to renew leases.
/// - Release
///
/// The purpose of the RateControl class is to track the due time for
/// sending next message (or bunch of messages) to keep outbound rate
/// of particular messages at the desired level. The due time is calculated
/// using the desired rate value and the timestamp when the last message of
/// the particular type has been sent. That puts the responsibility on the
/// \c TestControl class to invoke the \c RateControl::updateSendDue, every
/// time the message is sent.
///
/// The \c RateControl object returns the number of messages to be sent at
/// the time. The number returned is 0, if perfdhcp shouldn't send any messages
/// yet, or 1 (sometimes more) if the send due time has been reached.
class
RateControl
{
public:
/// \brief Default constructor.
RateControl
();
/// \brief Constructor which sets desired rate and aggressivity.
///
/// \param rate A desired rate.
/// \param aggressivity A desired aggressivity.
RateControl
(
const
int
rate
,
const
int
aggressivity
);
/// \brief Returns the value of aggressivity.
int
getAggressivity
()
const
{
return
(
aggressivity_
);
}
/// \brief Returns current due time to send next message.
boost
::
posix_time
::
ptime
getDue
()
const
{
return
(
send_due_
);
}
/// \brief Returns number of messages to be sent "now".
///
/// This function calculates how many messages of the given type should
/// be sent immediately when the call to the function returns, to catch
/// up with the desired message rate.
///
/// The value returned depends on the due time calculated with the
/// \c RateControl::updateSendDue function and the current time. If
/// the due time has been hit, the non-zero number of messages is returned.
/// If the due time hasn't been hit, the number returned is 0.
///
/// If the rate is non-zero, the number of messages to be sent is calculated
/// as follows:
/// \code
/// num = duration * rate
/// \endcode
/// where <b>duration</b> is a time period between the due time to send
/// next set of messages and current time. The duration is expressed in
/// seconds with the fractional part having 6 or 9 digits (depending on
/// the timer resolution). If the calculated value is equal to 0, it is
/// rounded to 1, so as at least one message is sent.
///
/// The value of aggressivity limits the maximal number of messages to
/// be sent one after another. If the number of messages calculated with
/// the equation above exceeds the aggressivity, this function will return
/// the value equal to aggressivity.
///
/// If the rate is not specified (equal to 0), the value calculated by
/// this function is equal to aggressivity.
///
/// \return A number of messages to be sent immediately.
uint64_t
getOutboundMessageCount
();
/// \brief Returns the rate.
int
getRate
()
const
{
return
(
rate_
);
}
/// \brief Returns the value of the late send flag.
///
/// The flag returned by this function indicates whether the new due time
/// calculated by the \c RateControl::updateSendDue is in the past.
/// This value is used by the \c TestControl object to increment the counter
/// of the late sent messages in the \c StatsMgr.
bool
isLateSent
()
const
{
return
(
late_sent_
);
}
/// \brief Sets the value of aggressivity.
///
/// \param aggressivity A new value of aggressivity. This value must be
/// a positive integer.
/// \throw isc::BadValue if new value is not a positive integer.
void
setAggressivity
(
const
int
aggressivity
);
/// \brief Sets the new rate.
///
/// \param rate A new value of rate. This value must not be negative.
/// \throw isc::BadValue if new rate is negative.
void
setRate
(
const
int
rate
);
/// \brief Sets the value of the due time.
///
/// This function is intended for unit testing. It manipulates the value of
/// the due time. The parameter passed to this function specifies the
/// (positive or negative) number of seconds relative to current time.
///
/// \param offset A number of seconds relative to current time which
/// constitutes the new due time.
void
setRelativeDue
(
const
int
offset
);
/// \brief Sets the timestamp of the last sent message to current time.
void
updateSendTime
();
protected:
/// \brief Convenience function returning current time.
///
/// \return current time.
static
boost
::
posix_time
::
ptime
currentTime
();
/// \brief Calculates the send due.
///
/// This function calculates the send due timestamp using the current time
/// and desired rate. The due timestamp is calculated as a sum of the
/// timestamp when the last message was sent and the reciprocal of the rate
/// in micro or nanoseconds (depending on the timer resolution). If the rate
/// is not specified, the duration between two consecutive sends is one
/// timer tick.
void
updateSendDue
();
/// \brief Holds a timestamp when the next message should be sent.