From 257444c69f8ecf328c62b488861bc781aaf1022a Mon Sep 17 00:00:00 2001 From: Tomek Mrugalski Date: Thu, 12 May 2011 14:01:15 +0000 Subject: [PATCH] - If a client renews before 'dhcp-cache-threshold' percent of its lease has elapsed (default 25%), the server will reuse the allocated lease (provide a lease within the currently allocated lease-time) rather than extend or renew the lease. This absolves the server of needing to perform an fsync() operation on the lease database before reply, which improves performance. [ISC-Bugs #22228] --- RELNOTES | 8 +++++- includes/dhcpd.h | 46 ++++++++++++++++++---------------- server/dhcp.c | 61 ++++++++++++++++++++++++++++++++++++++++++--- server/dhcpd.conf.5 | 26 ++++++++++++++++++- server/stables.c | 1 + 5 files changed, 116 insertions(+), 26 deletions(-) diff --git a/RELNOTES b/RELNOTES index fde0124f1..9ae00bb27 100644 --- a/RELNOTES +++ b/RELNOTES @@ -132,6 +132,13 @@ work on other platforms. Please report any problems and suggested fixes to - Compilation problem with gcc4.5 and omshell.c resolved. [ISC-Bugs #23831] +- If a client renews before 'dhcp-cache-threshold' percent of its lease + has elapsed (default 25%), the server will reuse the allocated lease + (provide a lease within the currently allocated lease-time) rather + than extend or renew the lease. This absolves the server of needing + to perform an fsync() operation on the lease database before reply, + which improves performance. [ISC-Bugs #22228] + Changes since 4.2.1rc1 - None @@ -160,7 +167,6 @@ work on other platforms. Please report any problems and suggested fixes to - Modify the dlpi code to accept getmsg() returning a positive value. [ISC-Bugs #22824] - Changes since 4.2.0 - 'get-host-names true;' now also works even if 'use-host-decl-names true;' diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 1ec7305ed..29aa1e9fe 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -691,6 +691,29 @@ struct lease_state { #define SV_LIMIT_PREFS_PER_IA 57 #define SV_DELAYED_ACK 58 #define SV_MAX_ACK_DELAY 59 +#if defined(LDAP_CONFIGURATION) +# define SV_LDAP_SERVER 60 +# define SV_LDAP_PORT 61 +# define SV_LDAP_USERNAME 62 +# define SV_LDAP_PASSWORD 63 +# define SV_LDAP_BASE_DN 64 +# define SV_LDAP_METHOD 65 +# define SV_LDAP_DEBUG_FILE 66 +# define SV_LDAP_DHCP_SERVER_CN 67 +# define SV_LDAP_REFERRALS 68 +#if defined (LDAP_USE_SSL) +# define SV_LDAP_SSL 69 +# define SV_LDAP_TLS_REQCERT 70 +# define SV_LDAP_TLS_CA_FILE 71 +# define SV_LDAP_TLS_CA_DIR 72 +# define SV_LDAP_TLS_CERT 73 +# define SV_LDAP_TLS_KEY 74 +# define SV_LDAP_TLS_CRLCHECK 75 +# define SV_LDAP_TLS_CIPHERS 76 +# define SV_LDAP_TLS_RANDFILE 77 +#endif +#endif +#define SV_CACHE_THRESHOLD 78 #if !defined (DEFAULT_PING_TIMEOUT) # define DEFAULT_PING_TIMEOUT 1 @@ -712,27 +735,8 @@ struct lease_state { # define DEFAULT_MIN_ACK_DELAY_USECS 10000 /* 1/100 second */ #endif -#if defined(LDAP_CONFIGURATION) -# define SV_LDAP_SERVER 60 -# define SV_LDAP_PORT 61 -# define SV_LDAP_USERNAME 62 -# define SV_LDAP_PASSWORD 63 -# define SV_LDAP_BASE_DN 64 -# define SV_LDAP_METHOD 65 -# define SV_LDAP_DEBUG_FILE 66 -# define SV_LDAP_DHCP_SERVER_CN 67 -# define SV_LDAP_REFERRALS 68 -#if defined (LDAP_USE_SSL) -# define SV_LDAP_SSL 69 -# define SV_LDAP_TLS_REQCERT 70 -# define SV_LDAP_TLS_CA_FILE 71 -# define SV_LDAP_TLS_CA_DIR 72 -# define SV_LDAP_TLS_CERT 73 -# define SV_LDAP_TLS_KEY 74 -# define SV_LDAP_TLS_CRLCHECK 75 -# define SV_LDAP_TLS_CIPHERS 76 -# define SV_LDAP_TLS_RANDFILE 77 -#endif +#if !defined (DEFAULT_CACHE_THRESHOLD) +# define DEFAULT_CACHE_THRESHOLD 25 #endif #if !defined (DEFAULT_DEFAULT_LEASE_TIME) diff --git a/server/dhcp.c b/server/dhcp.c index cce0951f3..3ca61912b 100644 --- a/server/dhcp.c +++ b/server/dhcp.c @@ -1502,6 +1502,10 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) struct in_addr from; TIME remaining_time; struct iaddr cip; +#if defined(DELAYED_ACK) + isc_boolean_t enqueue = ISC_TRUE; +#endif + int use_old_lease = 0; unsigned i, j; int s1; @@ -2445,6 +2449,48 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) packet -> raw -> chaddr, sizeof packet -> raw -> chaddr); /* XXX */ } else { + int commit = (!offer || (offer == DHCPACK)); + int thresh = DEFAULT_CACHE_THRESHOLD; + + /* + * Check if the lease was issued recently, if so replay the + * current lease and do not require a database sync event. + * Recently is defined as being issued less than a given + * percentage of the lease previously. The percentage can be + * chosen either from a default value or via configuration. + * + */ + if ((oc = lookup_option(&server_universe, state->options, + SV_CACHE_THRESHOLD)) && + evaluate_option_cache(&d1, packet, lt, NULL, + packet->options, state->options, + <->scope, oc, MDL)) { + if (d1.len == 1 && + (d1.data[0] >= 0) && (d1.data[0] < 100)) + thresh = d1.data[0]; + + data_string_forget(&d1, MDL); + } + + if ((thresh > 0) && (offer == DHCPACK) && + (lease->binding_state == FTS_ACTIVE)) { + int limit; + int prev_lease = lease->ends - lease->starts; + + /* it is better to avoid division by 0 */ + if (prev_lease <= (INT_MAX / thresh)) + limit = prev_lease * thresh / 100; + else + limit = prev_lease / 100 * thresh; + + if ((lt->starts - lease->starts) <= limit) { + lt->starts = lease->starts; + state->offered_expiry = lt->ends = lease->ends; + commit = 0; + use_old_lease = 1; + } + } + #if !defined(DELAYED_ACK) /* Install the new information on 'lt' onto the lease at * 'lease'. If this is a DHCPOFFER, it is a 'soft' promise, @@ -2454,9 +2500,19 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) * the same lease to another client later, and that would be * a conflict. */ - if (!supersede_lease(lease, lt, !offer || (offer == DHCPACK), + if (!use_old_lease && !supersede_lease(lease, lt, commit, offer == DHCPACK, offer == DHCPACK)) { #else /* defined(DELAYED_ACK) */ + /* + * If there already isn't a need for a lease commit, and we + * can just answer right away, set a flag to indicate this. + */ + if (commit && !(lease->flags & STATIC_LEASE) && + (!offer || (offer == DHCPACK))) + enqueue = ISC_TRUE; + else + enqueue = ISC_FALSE; + /* Install the new information on 'lt' onto the lease at * 'lease'.  We will not 'commit' this information to disk * yet (fsync()), we will 'propogate' the information if @@ -2865,8 +2921,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp) } else { lease->cltt = cur_time; #if defined(DELAYED_ACK) - if (!(lease->flags & STATIC_LEASE) && - (!offer || (offer == DHCPACK))) + if (enqueue) delayed_ack_enqueue(lease); else #endif diff --git a/server/dhcpd.conf.5 b/server/dhcpd.conf.5 index 2b3796f21..f6004c991 100644 --- a/server/dhcpd.conf.5 +++ b/server/dhcpd.conf.5 @@ -27,7 +27,7 @@ .\" Support and other services are available for ISC products - see .\" https://www.isc.org for more information or to learn more about ISC. .\" -.\" $Id: dhcpd.conf.5,v 1.106.18.3 2011/04/25 23:49:52 sar Exp $ +.\" $Id: dhcpd.conf.5,v 1.106.18.4 2011/05/12 14:01:15 tomasz Exp $ .\" .TH dhcpd.conf 5 .SH NAME @@ -2158,6 +2158,30 @@ feature is not compiled in by default, but must be enabled at compile time with \'./configure --enable-delayed-ack\'. .RE .PP +The +.I dhcp-cache-threshold +statement +.RS 0.25i +.PP +.B dhcp-cache-threshold \fIpercentage\fB;\fR +.PP +The \fIdhcp-cache-threshold\fR statement takes one integer parameter +with allowed values between 0 and 100. The default value is 25 (25% of +the lease time). This parameter expresses the percentage of the total +lease time, measured from the beginning, during which a +client's attempt to renew its lease will result in getting +the already assigned lease, rather than an extended lease. +.PP +Clients that attempt renewal frequently can cause the server to +update and write the database frequently resulting in a performance +impact on the server. The \fIdhcp-cache-threshold\fR +statement instructs the DHCP server to avoid updating leases too +frequently thus avoiding this behavior. Instead the server assigns the +same lease with no modifications except for CLTT (Client Last +Transmission Time) which does not require disk operations. This +feature applies to IPv4 only. +.RE +.PP The .I do-forward-updates statement diff --git a/server/stables.c b/server/stables.c index 829452774..a8e499890 100644 --- a/server/stables.c +++ b/server/stables.c @@ -266,6 +266,7 @@ static struct option server_options[] = { { "ldap-tls-randfile", "t", &server_universe, 77, 1 }, #endif /* LDAP_USE_SSL */ #endif /* LDAP_CONFIGURATION */ + { "dhcp-cache-threshold", "B", &server_universe, 78, 1 }, { NULL, NULL, NULL, 0, 0 } }; -- 2.47.3