mirror of
https://gitlab.isc.org/isc-projects/dhcp
synced 2025-08-22 09:57:20 +00:00
[master] Add support for pool thresholds
Add support to set high and low thresholds for pools for v4 and v6. A message will be emitted when the usage of the pool first exceeds the high threshold. More messages will be skipped until the usage has gone below the low threshold and then back above the high threshold.
This commit is contained in:
parent
0ab4a71612
commit
250f7134bb
6
RELNOTES
6
RELNOTES
@ -164,6 +164,12 @@ by Eric Young (eay@cryptsoft.com).
|
||||
process to start up even if the resolv.conf file has problems.
|
||||
[ISC-Bugs #35989]
|
||||
|
||||
- Add theshold logging functionality. Two new options,
|
||||
log-threshold-low and log-threshold-high, indicate to the
|
||||
server if and when it should log an error message as addresses
|
||||
in a pool are used.
|
||||
[ISC-Bugs #34487]
|
||||
|
||||
Changes since 4.3.0rc1
|
||||
|
||||
- None
|
||||
|
@ -2126,6 +2126,57 @@ int get_option (result, universe, packet, lease, client_state,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for the option and dig out the value assoicated with it.
|
||||
* Currently this is used for 1 byte integers, it maybe expanded
|
||||
* in the future to handle other integers at which point it will
|
||||
* need a size argument.
|
||||
*/
|
||||
int get_option_int (result, universe, packet, lease, client_state,
|
||||
in_options, cfg_options, options, scope, code, file, line)
|
||||
int *result;
|
||||
struct universe *universe;
|
||||
struct packet *packet;
|
||||
struct lease *lease;
|
||||
struct client_state *client_state;
|
||||
struct option_state *in_options;
|
||||
struct option_state *cfg_options;
|
||||
struct option_state *options;
|
||||
struct binding_scope **scope;
|
||||
unsigned code;
|
||||
const char *file;
|
||||
int line;
|
||||
{
|
||||
struct option_cache *oc;
|
||||
struct data_string d1;
|
||||
int rcode = 0;
|
||||
|
||||
/* basic sanity checks */
|
||||
if ((options == NULL) || (universe->lookup_func == NULL))
|
||||
return (0);
|
||||
|
||||
/* find the option cache */
|
||||
oc = ((*universe->lookup_func)(universe, options, code));
|
||||
if (!oc)
|
||||
return (0);
|
||||
|
||||
/* if there is a value get it into the string */
|
||||
memset(&d1, 0, sizeof(d1));
|
||||
if (!evaluate_option_cache(&d1, packet, lease, client_state,
|
||||
in_options, cfg_options, scope, oc,
|
||||
file, line))
|
||||
return (0);
|
||||
|
||||
/* If the length matches extract the value for the return */
|
||||
if (d1.len == 1) {
|
||||
*result = d1.data[0];
|
||||
rcode = 1;
|
||||
}
|
||||
data_string_forget(&d1, MDL);
|
||||
|
||||
return (rcode);
|
||||
}
|
||||
|
||||
void set_option (universe, options, option, op)
|
||||
struct universe *universe;
|
||||
struct option_state *options;
|
||||
|
@ -8,7 +8,7 @@ ATF_TESTS =
|
||||
|
||||
if HAVE_ATF
|
||||
|
||||
ATF_TESTS += alloc_unittest dns_unittest
|
||||
ATF_TESTS += alloc_unittest dns_unittest misc_unittest
|
||||
|
||||
alloc_unittest_SOURCES = test_alloc.c $(top_srcdir)/tests/t_api_dhcp.c
|
||||
alloc_unittest_LDADD = $(ATF_LDFLAGS)
|
||||
@ -22,6 +22,12 @@ dns_unittest_LDADD += ../libdhcp.a \
|
||||
../../omapip/libomapi.a ../../bind/lib/libirs.a \
|
||||
../../bind/lib/libdns.a ../../bind/lib/libisccfg.a ../../bind/lib/libisc.a
|
||||
|
||||
misc_unittest_SOURCES = misc_unittest.c $(top_srcdir)/tests/t_api_dhcp.c
|
||||
misc_unittest_LDADD = $(ATF_LDFLAGS)
|
||||
misc_unittest_LDADD += ../libdhcp.a \
|
||||
../../omapip/libomapi.a ../../bind/lib/libirs.a \
|
||||
../../bind/lib/libdns.a ../../bind/lib/libisccfg.a ../../bind/lib/libisc.a
|
||||
|
||||
check: $(ATF_TESTS)
|
||||
atf-run | atf-report
|
||||
|
||||
|
@ -77,7 +77,7 @@ PRE_UNINSTALL = :
|
||||
POST_UNINSTALL = :
|
||||
build_triplet = @build@
|
||||
host_triplet = @host@
|
||||
@HAVE_ATF_TRUE@am__append_1 = alloc_unittest dns_unittest
|
||||
@HAVE_ATF_TRUE@am__append_1 = alloc_unittest dns_unittest misc_unittest
|
||||
check_PROGRAMS = $(am__EXEEXT_2)
|
||||
subdir = common/tests
|
||||
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
|
||||
@ -91,7 +91,7 @@ CONFIG_HEADER = $(top_builddir)/includes/config.h
|
||||
CONFIG_CLEAN_FILES =
|
||||
CONFIG_CLEAN_VPATH_FILES =
|
||||
@HAVE_ATF_TRUE@am__EXEEXT_1 = alloc_unittest$(EXEEXT) \
|
||||
@HAVE_ATF_TRUE@ dns_unittest$(EXEEXT)
|
||||
@HAVE_ATF_TRUE@ dns_unittest$(EXEEXT) misc_unittest$(EXEEXT)
|
||||
am__EXEEXT_2 = $(am__EXEEXT_1)
|
||||
am__alloc_unittest_SOURCES_DIST = test_alloc.c \
|
||||
$(top_srcdir)/tests/t_api_dhcp.c
|
||||
@ -114,6 +114,16 @@ dns_unittest_OBJECTS = $(am_dns_unittest_OBJECTS)
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libirs.a ../../bind/lib/libdns.a \
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libisccfg.a \
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libisc.a
|
||||
am__misc_unittest_SOURCES_DIST = misc_unittest.c \
|
||||
$(top_srcdir)/tests/t_api_dhcp.c
|
||||
@HAVE_ATF_TRUE@am_misc_unittest_OBJECTS = misc_unittest.$(OBJEXT) \
|
||||
@HAVE_ATF_TRUE@ t_api_dhcp.$(OBJEXT)
|
||||
misc_unittest_OBJECTS = $(am_misc_unittest_OBJECTS)
|
||||
@HAVE_ATF_TRUE@misc_unittest_DEPENDENCIES = $(am__DEPENDENCIES_1) \
|
||||
@HAVE_ATF_TRUE@ ../libdhcp.a ../../omapip/libomapi.a \
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libirs.a ../../bind/lib/libdns.a \
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libisccfg.a \
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libisc.a
|
||||
AM_V_P = $(am__v_P_@AM_V@)
|
||||
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
|
||||
am__v_P_0 = false
|
||||
@ -146,9 +156,11 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
|
||||
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
|
||||
am__v_CCLD_0 = @echo " CCLD " $@;
|
||||
am__v_CCLD_1 =
|
||||
SOURCES = $(alloc_unittest_SOURCES) $(dns_unittest_SOURCES)
|
||||
SOURCES = $(alloc_unittest_SOURCES) $(dns_unittest_SOURCES) \
|
||||
$(misc_unittest_SOURCES)
|
||||
DIST_SOURCES = $(am__alloc_unittest_SOURCES_DIST) \
|
||||
$(am__dns_unittest_SOURCES_DIST)
|
||||
$(am__dns_unittest_SOURCES_DIST) \
|
||||
$(am__misc_unittest_SOURCES_DIST)
|
||||
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
|
||||
ctags-recursive dvi-recursive html-recursive info-recursive \
|
||||
install-data-recursive install-dvi-recursive \
|
||||
@ -334,6 +346,12 @@ ATF_TESTS = $(am__append_1)
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libdns.a \
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libisccfg.a \
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libisc.a
|
||||
@HAVE_ATF_TRUE@misc_unittest_SOURCES = misc_unittest.c $(top_srcdir)/tests/t_api_dhcp.c
|
||||
@HAVE_ATF_TRUE@misc_unittest_LDADD = $(ATF_LDFLAGS) ../libdhcp.a \
|
||||
@HAVE_ATF_TRUE@ ../../omapip/libomapi.a ../../bind/lib/libirs.a \
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libdns.a \
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libisccfg.a \
|
||||
@HAVE_ATF_TRUE@ ../../bind/lib/libisc.a
|
||||
all: all-recursive
|
||||
|
||||
.SUFFIXES:
|
||||
@ -380,6 +398,10 @@ dns_unittest$(EXEEXT): $(dns_unittest_OBJECTS) $(dns_unittest_DEPENDENCIES) $(EX
|
||||
@rm -f dns_unittest$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(dns_unittest_OBJECTS) $(dns_unittest_LDADD) $(LIBS)
|
||||
|
||||
misc_unittest$(EXEEXT): $(misc_unittest_OBJECTS) $(misc_unittest_DEPENDENCIES) $(EXTRA_misc_unittest_DEPENDENCIES)
|
||||
@rm -f misc_unittest$(EXEEXT)
|
||||
$(AM_V_CCLD)$(LINK) $(misc_unittest_OBJECTS) $(misc_unittest_LDADD) $(LIBS)
|
||||
|
||||
mostlyclean-compile:
|
||||
-rm -f *.$(OBJEXT)
|
||||
|
||||
@ -387,6 +409,7 @@ distclean-compile:
|
||||
-rm -f *.tab.c
|
||||
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dns_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/misc_unittest.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_api_dhcp.Po@am__quote@
|
||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test_alloc.Po@am__quote@
|
||||
|
||||
|
166
common/tests/misc_unittest.c
Normal file
166
common/tests/misc_unittest.c
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (C) 2014 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 <config.h>
|
||||
#include <atf-c.h>
|
||||
#include "dhcpd.h"
|
||||
|
||||
struct basic_test {
|
||||
int count;
|
||||
int used_0;
|
||||
int used_25;
|
||||
int used_50;
|
||||
int used_75;
|
||||
int used_100;
|
||||
};
|
||||
|
||||
struct basic_test basic_values[] =
|
||||
{{ 0, 0, 0, 0, 0, 0},
|
||||
{ 10, 0, 2, 5, 7, 10},
|
||||
{ 20, 0, 5, 10, 15, 20},
|
||||
{ 50, 0, 12, 25, 37, 50},
|
||||
{ 100, 0, 25, 50, 75, 100},
|
||||
{ 1000, 0, 250, 500, 750, 1000},
|
||||
{ 10000, 0, 2500, 5000, 7500, 10000},
|
||||
{ 100000, 0, 25000, 50000, 75000, 100000},
|
||||
{ 1000000, 0, 250000, 500000, 750000, 1000000},
|
||||
{ 10000000, 0, 2500000, 5000000, 7500000, 10000000},
|
||||
{ 100000000, 0, 25000000, 50000000, 75000000, 100000000},
|
||||
{1000000000, 0, 250000000, 500000000, 750000000, 1000000000},
|
||||
{2000000000, 0, 500000000, 1000000000, 1500000000, 2000000000},
|
||||
{-1, 0, 0, 0, 0, 0}};
|
||||
|
||||
ATF_TC(find_percent_basic);
|
||||
|
||||
ATF_TC_HEAD(find_percent_basic, tc)
|
||||
{
|
||||
atf_tc_set_md_var(tc, "descr", "Verify basic percent calculation.");
|
||||
}
|
||||
|
||||
/* This test does a simple check to see if we get the right value
|
||||
* given a count and a percnetage of that count
|
||||
*/
|
||||
ATF_TC_BODY(find_percent_basic, tc)
|
||||
{
|
||||
struct basic_test *basic_value;
|
||||
int used;
|
||||
|
||||
for (basic_value = &basic_values[0];
|
||||
basic_value->count != -1;
|
||||
basic_value++) {
|
||||
used = FIND_PERCENT(basic_value->count, 0);
|
||||
if (used != basic_value->used_0) {
|
||||
atf_tc_fail("Wrong value for 0 - count: %d, used %d",
|
||||
basic_value->count, used);
|
||||
}
|
||||
|
||||
used = FIND_PERCENT(basic_value->count, 25);
|
||||
if (used != basic_value->used_25) {
|
||||
atf_tc_fail("Wrong value for 25 - count: %d, used %d",
|
||||
basic_value->count, used);
|
||||
}
|
||||
|
||||
used = FIND_PERCENT(basic_value->count, 50);
|
||||
if (used != basic_value->used_50) {
|
||||
atf_tc_fail("Wrong value for 50 - count: %d, used %d",
|
||||
basic_value->count, used);
|
||||
}
|
||||
|
||||
used = FIND_PERCENT(basic_value->count, 75);
|
||||
if (used != basic_value->used_75) {
|
||||
atf_tc_fail("Wrong value for 75 - count: %d, used %d",
|
||||
basic_value->count, used);
|
||||
}
|
||||
|
||||
used = FIND_PERCENT(basic_value->count, 100);
|
||||
if (used != basic_value->used_100) {
|
||||
atf_tc_fail("Wrong value for 100 - count: %d, used %d",
|
||||
basic_value->count, used);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ATF_TC(find_percent_adv);
|
||||
|
||||
ATF_TC_HEAD(find_percent_adv, tc)
|
||||
{
|
||||
atf_tc_set_md_var(tc, "descr", "Verify advanced percent calculation.");
|
||||
}
|
||||
|
||||
/* This test tries some more complicated items, such as using the macro
|
||||
* in a function or passing expressions into macro
|
||||
*/
|
||||
ATF_TC_BODY(find_percent_adv, tc)
|
||||
{
|
||||
if (FIND_PERCENT(10*10, 10) != 10) {
|
||||
atf_tc_fail("Wrong value for adv 1");
|
||||
}
|
||||
|
||||
if (FIND_PERCENT(20*20, 80) != 320) {
|
||||
atf_tc_fail("Wrong value for adv 2");
|
||||
}
|
||||
|
||||
if (FIND_PERCENT(1000000*1000, 50) != 500000000) {
|
||||
atf_tc_fail("Wrong value for adv 3");
|
||||
}
|
||||
|
||||
if (FIND_PERCENT(100+100, 10) != 20) {
|
||||
atf_tc_fail("Wrong value for adv 4");
|
||||
}
|
||||
|
||||
if (FIND_PERCENT(1000+2000, 90) != 2700) {
|
||||
atf_tc_fail("Wrong value for adv 5");
|
||||
}
|
||||
|
||||
if (FIND_PERCENT(10000 - 8000, 70) != 1400) {
|
||||
atf_tc_fail("Wrong value for adv 6");
|
||||
}
|
||||
|
||||
if (FIND_PERCENT(2000000000 / 1000, 25) != 500000) {
|
||||
atf_tc_fail("Wrong value for adv 7");
|
||||
}
|
||||
|
||||
if (FIND_PERCENT(10*10, 10)/2 != 5) {
|
||||
atf_tc_fail("Wrong value for adv 8");
|
||||
}
|
||||
|
||||
if (FIND_PERCENT(100*10, 50) * 2 != 1000) {
|
||||
atf_tc_fail("Wrong value for adv 9");
|
||||
}
|
||||
|
||||
if (FIND_PERCENT(100*10, 50) * 2 > 1000) {
|
||||
atf_tc_fail("Wrong value for adv 10");
|
||||
}
|
||||
|
||||
if (FIND_PERCENT(100+100, 20) * 2 < 60) {
|
||||
atf_tc_fail("Wrong value for adv 11");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* This macro defines main() method that will call specified
|
||||
test cases. tp and simple_test_case names can be whatever you want
|
||||
as long as it is a valid variable identifier. */
|
||||
ATF_TP_ADD_TCS(tp)
|
||||
{
|
||||
ATF_TP_ADD_TC(tp, find_percent_basic);
|
||||
ATF_TP_ADD_TC(tp, find_percent_adv);
|
||||
|
||||
return (atf_no_error());
|
||||
}
|
@ -730,6 +730,8 @@ struct lease_state {
|
||||
#define SV_DDNS_LOCAL_ADDRESS4 80
|
||||
#define SV_DDNS_LOCAL_ADDRESS6 81
|
||||
#define SV_IGNORE_CLIENT_UIDS 82
|
||||
#define SV_LOG_THRESHOLD_LOW 83
|
||||
#define SV_LOG_THRESHOLD_HIGH 84
|
||||
|
||||
#if !defined (DEFAULT_PING_TIMEOUT)
|
||||
# define DEFAULT_PING_TIMEOUT 1
|
||||
@ -925,6 +927,8 @@ struct pool {
|
||||
#if defined (FAILOVER_PROTOCOL)
|
||||
dhcp_failover_state_t *failover_peer;
|
||||
#endif
|
||||
int logged; /* already logged a message */
|
||||
int low_threshold; /* low threshold to restart logging */
|
||||
};
|
||||
|
||||
struct shared_network {
|
||||
@ -1606,6 +1610,10 @@ struct ipv6_pond {
|
||||
struct ipv6_pool **ipv6_pools; /* NULL-terminated array */
|
||||
int last_ipv6_pool; /* offset of last IPv6 pool
|
||||
used to issue a lease */
|
||||
int num_total; /* Total number of elements in the pond */
|
||||
int num_active; /* Number of elements in the pond in use */
|
||||
int logged; /* already logged a message */
|
||||
int low_threshold; /* low threshold to restart logging */
|
||||
};
|
||||
|
||||
/* Flags and state for dhcp_ddns_cb_t */
|
||||
@ -1774,6 +1782,11 @@ int get_option (struct data_string *, struct universe *,
|
||||
struct option_state *, struct option_state *,
|
||||
struct option_state *, struct binding_scope **, unsigned,
|
||||
const char *, int);
|
||||
int get_option_int (int *, struct universe *,
|
||||
struct packet *, struct lease *, struct client_state *,
|
||||
struct option_state *, struct option_state *,
|
||||
struct option_state *, struct binding_scope **, unsigned,
|
||||
const char *, int);
|
||||
void set_option (struct universe *, struct option_state *,
|
||||
struct option_cache *, enum statement_op);
|
||||
struct option_cache *lookup_option (struct universe *,
|
||||
@ -3617,3 +3630,12 @@ void mark_interfaces_unavailable(void);
|
||||
|
||||
#define MAX_ADDRESS_STRING_LEN \
|
||||
(sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"))
|
||||
|
||||
/* Find the percentage of count. We need to try two different
|
||||
* ways to avoid rounding mistakes.
|
||||
*/
|
||||
#define FIND_PERCENT(count, percent) \
|
||||
((count) > (INT_MAX / 100) ? \
|
||||
((count) / 100) * (percent) : ((count) * (percent)) / 100)
|
||||
|
||||
|
||||
|
@ -3837,6 +3837,12 @@ add_ipv6_pool_to_subnet(struct subnet *subnet, u_int16_t type,
|
||||
*/
|
||||
ipv6_pool_reference(&pond->ipv6_pools[num_pools], pool, MDL);
|
||||
pond->ipv6_pools[num_pools+1] = NULL;
|
||||
/* Update the number of elements in the pond. Conveniently
|
||||
* we have the total size of the block in bits and the amount
|
||||
* we would allocate per element in units. For an address units
|
||||
* will always be 128, for a prefix it will be something else.
|
||||
*/
|
||||
pond->num_total += 1 << (units - bits);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
102
server/dhcp.c
102
server/dhcp.c
@ -1745,6 +1745,98 @@ void nak_lease (packet, cip)
|
||||
|
||||
}
|
||||
|
||||
void check_pool_threshold (packet, lease, state)
|
||||
struct packet *packet;
|
||||
struct lease *lease;
|
||||
struct lease_state *state;
|
||||
|
||||
{
|
||||
|
||||
struct pool *pool = lease->pool;
|
||||
int used, count, high_threshold, poolhigh = 0, poollow = 0;
|
||||
char *shared_name = "no name";
|
||||
|
||||
if (pool == NULL)
|
||||
return;
|
||||
|
||||
/* get a pointer to the name if we have one */
|
||||
if ((pool->shared_network != NULL) &&
|
||||
(pool->shared_network->name != NULL)) {
|
||||
shared_name = pool->shared_network->name;
|
||||
}
|
||||
|
||||
count = pool->lease_count;
|
||||
used = count - (pool->free_leases + pool->backup_leases);
|
||||
|
||||
/* The logged flag indicates if we have already crossed the high
|
||||
* threshold and emitted a log message. If it is set we check to
|
||||
* see if we have re-crossed the low threshold and need to reset
|
||||
* things. When we cross the high threshold we determine what
|
||||
* the low threshold is and save it into the low_threshold value.
|
||||
* When we cross that threshold we reset the logged flag and
|
||||
* the low_threshold to 0 which allows the high threshold message
|
||||
* to be emitted once again.
|
||||
* if we haven't recrossed the boundry we don't need to do anything.
|
||||
*/
|
||||
if (pool->logged !=0) {
|
||||
if (used <= pool->low_threshold) {
|
||||
pool->low_threshold = 0;
|
||||
pool->logged = 0;
|
||||
log_error("Pool threshold reset - shared subnet: %s; "
|
||||
"address: %s; low threshold %d/%d.",
|
||||
shared_name, piaddr(lease->ip_addr),
|
||||
used, count);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* find the high threshold */
|
||||
if (get_option_int(&poolhigh, &server_universe, packet, lease, NULL,
|
||||
packet->options, state->options, state->options,
|
||||
&lease->scope, SV_LOG_THRESHOLD_HIGH, MDL) == 0) {
|
||||
/* no threshold bail out */
|
||||
return;
|
||||
}
|
||||
|
||||
/* We do have a threshold for this pool, see if its valid */
|
||||
if ((poolhigh <= 0) || (poolhigh > 100)) {
|
||||
/* not valid */
|
||||
return;
|
||||
}
|
||||
|
||||
/* we have a valid value, have we exceeded it */
|
||||
high_threshold = FIND_PERCENT(count, poolhigh);
|
||||
if (used < high_threshold) {
|
||||
/* nope, no more to do */
|
||||
return;
|
||||
}
|
||||
|
||||
/* we've exceeded it, output a message */
|
||||
log_error("Pool threshold exceeded - shared subnet: %s; "
|
||||
"address: %s; high threshold %d%% %d/%d.",
|
||||
shared_name, piaddr(lease->ip_addr),
|
||||
poolhigh, used, count);
|
||||
|
||||
/* handle the low threshold now, if we don't
|
||||
* have a valid one we default to 0. */
|
||||
if ((get_option_int(&poollow, &server_universe, packet, lease, NULL,
|
||||
packet->options, state->options, state->options,
|
||||
&lease->scope, SV_LOG_THRESHOLD_LOW, MDL) == 0) ||
|
||||
(poollow > 100)) {
|
||||
poollow = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the low theshold is higher than the high threshold we continue to log
|
||||
* If it isn't then we set the flag saying we already logged and determine
|
||||
* what the reset threshold is.
|
||||
*/
|
||||
if (poollow < poolhigh) {
|
||||
pool->logged = 1;
|
||||
pool->low_threshold = FIND_PERCENT(count, poollow);
|
||||
}
|
||||
}
|
||||
|
||||
void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
|
||||
struct packet *packet;
|
||||
struct lease *lease;
|
||||
@ -2390,6 +2482,14 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
|
||||
data_string_forget(&d1, MDL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* If this is an ack check to see if we have used enough of
|
||||
* the pool to want to log a message
|
||||
*/
|
||||
if (offer == DHCPACK)
|
||||
check_pool_threshold(packet, lease, state);
|
||||
|
||||
/* a client requests an address which is not yet active*/
|
||||
if (lease->pool && lease->pool->valid_from &&
|
||||
cur_time < lease->pool->valid_from) {
|
||||
@ -2410,7 +2510,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
|
||||
b) extend lease only up to the expiration date, but not
|
||||
below min-lease-time
|
||||
Setting min-lease-time is essential for this to work!
|
||||
The value of min-lease-time determines the lenght
|
||||
The value of min-lease-time determines the length
|
||||
of the transition window:
|
||||
A client renewing a second before the deadline will
|
||||
get a min-lease-time lease. Since the current ip might not
|
||||
|
@ -2476,6 +2476,31 @@ possible.
|
||||
.RE
|
||||
.PP
|
||||
The
|
||||
.I log-threshold-high
|
||||
and
|
||||
.I log-threshold-low
|
||||
statements
|
||||
.RS 0.25i
|
||||
.PP
|
||||
.B log-threshold-high \fIpercentage\fB;\fR
|
||||
.PP
|
||||
.B log-threshold-low \fIpercentage\fB;\fR
|
||||
.PP
|
||||
The \fIlog-threshold-low\fR and \fIlog-threshold-high\fR statements
|
||||
are used to control when a message is output about pool usage. The
|
||||
value for both of them is the percentage of the pool in use. If the
|
||||
high threshold is 0 or has not been specified, no messages will be
|
||||
produced. If a high threshold is given, a message is output once the
|
||||
pool usage passes that level. After that, no more messages will be
|
||||
output until the pool usage falls below the low threshold. If the low
|
||||
threshold is not given, it default to a value of zero.
|
||||
.PP
|
||||
A special case occurs when the low threshold is set to be higer than
|
||||
the high threshold. In this case, a message will be generated each time
|
||||
a lease is acknowledged when the pool usage is above the high threshold.
|
||||
.RE
|
||||
.PP
|
||||
The
|
||||
.I max-lease-time
|
||||
statement
|
||||
.RS 0.25i
|
||||
|
100
server/dhcpv6.c
100
server/dhcpv6.c
@ -796,6 +796,99 @@ set_status_code(u_int16_t status_code, const char *status_message,
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
void check_pool6_threshold(struct reply_state *reply,
|
||||
struct iasubopt *lease)
|
||||
{
|
||||
struct ipv6_pond *pond;
|
||||
int used, count, high_threshold, poolhigh = 0, poollow = 0;
|
||||
char *shared_name = "no name";
|
||||
char tmp_addr[INET6_ADDRSTRLEN];
|
||||
|
||||
if ((lease->ipv6_pool == NULL) || (lease->ipv6_pool->ipv6_pond == NULL))
|
||||
return;
|
||||
pond = lease->ipv6_pool->ipv6_pond;
|
||||
|
||||
count = pond->num_total;
|
||||
used = pond->num_active;
|
||||
|
||||
/* The logged flag indicates if we have already crossed the high
|
||||
* threshold and emitted a log message. If it is set we check to
|
||||
* see if we have re-crossed the low threshold and need to reset
|
||||
* things. When we cross the high threshold we determine what
|
||||
* the low threshold is and save it into the low_threshold value.
|
||||
* When we cross that threshold we reset the logged flag and
|
||||
* the low_threshold to 0 which allows the high threshold message
|
||||
* to be emitted once again.
|
||||
* if we haven't recrossed the boundry we don't need to do anything.
|
||||
*/
|
||||
if (pond->logged !=0) {
|
||||
if (used <= pond->low_threshold) {
|
||||
pond->low_threshold = 0;
|
||||
pond->logged = 0;
|
||||
log_error("Pool threshold reset - shared subnet: %s; "
|
||||
"address: %s; low threshold %d/%d.",
|
||||
shared_name,
|
||||
inet_ntop(AF_INET6, &lease->addr,
|
||||
tmp_addr, sizeof(tmp_addr)),
|
||||
used, count);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* find the high threshold */
|
||||
if (get_option_int(&poolhigh, &server_universe, reply->packet, NULL,
|
||||
NULL, reply->packet->options, reply->opt_state,
|
||||
reply->opt_state, &lease->scope,
|
||||
SV_LOG_THRESHOLD_HIGH, MDL) == 0) {
|
||||
/* no threshold bail out */
|
||||
return;
|
||||
}
|
||||
|
||||
/* We do have a threshold for this pool, see if its valid */
|
||||
if ((poolhigh <= 0) || (poolhigh > 100)) {
|
||||
/* not valid */
|
||||
return;
|
||||
}
|
||||
|
||||
/* we have a valid value, have we exceeded it */
|
||||
high_threshold = FIND_PERCENT(count, poolhigh);
|
||||
if (used < high_threshold) {
|
||||
/* nope, no more to do */
|
||||
return;
|
||||
}
|
||||
|
||||
/* we've exceeded it, output a message */
|
||||
if ((pond->shared_network != NULL) &&
|
||||
(pond->shared_network->name != NULL)) {
|
||||
shared_name = pond->shared_network->name;
|
||||
}
|
||||
log_error("Pool threshold exceeded - shared subnet: %s; "
|
||||
"address: %s; high threshold %d%% %d/%d.",
|
||||
shared_name,
|
||||
inet_ntop(AF_INET6, &lease->addr, tmp_addr, sizeof(tmp_addr)),
|
||||
poolhigh, used, count);
|
||||
|
||||
/* handle the low threshold now, if we don't
|
||||
* have one we default to 0. */
|
||||
if ((get_option_int(&poollow, &server_universe, reply->packet, NULL,
|
||||
NULL, reply->packet->options, reply->opt_state,
|
||||
reply->opt_state, &lease->scope,
|
||||
SV_LOG_THRESHOLD_LOW, MDL) == 0) ||
|
||||
(poollow > 100)) {
|
||||
poollow = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the low theshold is higher than the high threshold we continue to log
|
||||
* If it isn't then we set the flag saying we already logged and determine
|
||||
* what the reset threshold is.
|
||||
*/
|
||||
if (poollow < poolhigh) {
|
||||
pond->logged = 1;
|
||||
pond->low_threshold = FIND_PERCENT(count, poollow);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a set of operations we do to set up the reply packet, which
|
||||
* is the same for many message types.
|
||||
@ -1939,6 +2032,8 @@ reply_process_ia_na(struct reply_state *reply, struct option_cache *ia) {
|
||||
tmp, NULL, reply->opt_state);
|
||||
}
|
||||
#endif
|
||||
/* Do our threshold check. */
|
||||
check_pool6_threshold(reply, tmp);
|
||||
}
|
||||
|
||||
/* Remove any old ia from the hash. */
|
||||
@ -2655,6 +2750,8 @@ reply_process_ia_ta(struct reply_state *reply, struct option_cache *ia) {
|
||||
tmp, NULL, reply->opt_state);
|
||||
}
|
||||
#endif
|
||||
/* Do our threshold check. */
|
||||
check_pool6_threshold(reply, tmp);
|
||||
}
|
||||
|
||||
/* Remove any old ia from the hash. */
|
||||
@ -3713,6 +3810,9 @@ reply_process_ia_pd(struct reply_state *reply, struct option_cache *ia) {
|
||||
executable_statement_dereference
|
||||
(&tmp->on_star.on_commit, MDL);
|
||||
}
|
||||
|
||||
/* Do our threshold check. */
|
||||
check_pool6_threshold(reply, tmp);
|
||||
}
|
||||
|
||||
/* Remove any old ia from the hash. */
|
||||
|
@ -1188,6 +1188,8 @@ cleanup_lease6(ia_hash_t *ia_table,
|
||||
*/
|
||||
isc_heap_delete(pool->active_timeouts, test_iasubopt->heap_index);
|
||||
pool->num_active--;
|
||||
if (pool->ipv6_pond)
|
||||
pool->ipv6_pond->num_active--;
|
||||
|
||||
iasubopt_hash_delete(pool->leases, &test_iasubopt->addr,
|
||||
sizeof(test_iasubopt->addr), MDL);
|
||||
@ -1253,6 +1255,8 @@ add_lease6(struct ipv6_pool *pool, struct iasubopt *lease,
|
||||
isc_heap_delete(pool->active_timeouts,
|
||||
test_iasubopt->heap_index);
|
||||
pool->num_active--;
|
||||
if (pool->ipv6_pond)
|
||||
pool->ipv6_pond->num_active--;
|
||||
} else {
|
||||
isc_heap_delete(pool->inactive_timeouts,
|
||||
test_iasubopt->heap_index);
|
||||
@ -1287,8 +1291,12 @@ add_lease6(struct ipv6_pool *pool, struct iasubopt *lease,
|
||||
sizeof(tmp_iasubopt->addr), lease, MDL);
|
||||
insert_result = isc_heap_insert(pool->active_timeouts,
|
||||
tmp_iasubopt);
|
||||
if (insert_result == ISC_R_SUCCESS)
|
||||
if (insert_result == ISC_R_SUCCESS) {
|
||||
pool->num_active++;
|
||||
if (pool->ipv6_pond)
|
||||
pool->ipv6_pond->num_active++;
|
||||
}
|
||||
|
||||
} else {
|
||||
tmp_iasubopt->soft_lifetime_end_time = valid_lifetime_end_time;
|
||||
insert_result = isc_heap_insert(pool->inactive_timeouts,
|
||||
@ -1377,6 +1385,8 @@ move_lease_to_active(struct ipv6_pool *pool, struct iasubopt *lease) {
|
||||
pool->num_active++;
|
||||
pool->num_inactive--;
|
||||
lease->state = FTS_ACTIVE;
|
||||
if (pool->ipv6_pond)
|
||||
pool->ipv6_pond->num_active++;
|
||||
}
|
||||
return insert_result;
|
||||
}
|
||||
@ -1503,6 +1513,8 @@ move_lease_to_inactive(struct ipv6_pool *pool, struct iasubopt *lease,
|
||||
lease->state = state;
|
||||
pool->num_active--;
|
||||
pool->num_inactive++;
|
||||
if (pool->ipv6_pond)
|
||||
pool->ipv6_pond->num_active--;
|
||||
}
|
||||
return insert_result;
|
||||
}
|
||||
|
@ -265,6 +265,8 @@ static struct option server_options[] = {
|
||||
{ "ddns-local-address4", "I", &server_universe, 80, 1 },
|
||||
{ "ddns-local-address6", "6", &server_universe, 81, 1 },
|
||||
{ "ignore-client-uids", "f", &server_universe, 82, 1 },
|
||||
{ "log-threshold-low", "B", &server_universe, 83, 1 },
|
||||
{ "log-threshold-high", "B", &server_universe, 84, 1 },
|
||||
{ NULL, NULL, NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user