2
0
mirror of https://gitlab.isc.org/isc-projects/dhcp synced 2025-09-02 15:25:48 +00:00

[master] Delayed-ack now works correctly with failover

Merges in 31474.
This commit is contained in:
Thomas Markwalder
2015-06-15 15:19:42 -04:00
parent 3933e2aa51
commit e422b8c78f
5 changed files with 65 additions and 33 deletions

View File

@@ -54,6 +54,11 @@ by Eric Young (eay@cryptsoft.com).
Changes since 4.3.2 Changes since 4.3.2
- Delayed-ack now works properly with Failover. Prior to this, bind updates
post startup were being queued but never delivered. Among other things, this
was causing leases to not transition from expired or released to free.
[ISC-Bugs #31474]
- The server now does a better check to see if it can allocate the memory - The server now does a better check to see if it can allocate the memory
for large blocks of v4 leases and should provide a slightly better error for large blocks of v4 leases and should provide a slightly better error
message. Note well: the server pre-allocates v4 addresses, if you use message. Note well: the server pre-allocates v4 addresses, if you use

View File

@@ -2313,9 +2313,7 @@ void ack_lease (struct packet *, struct lease *,
unsigned int, TIME, char *, int, struct host_decl *); unsigned int, TIME, char *, int, struct host_decl *);
void echo_client_id(struct packet*, struct lease*, struct option_state*, void echo_client_id(struct packet*, struct lease*, struct option_state*,
struct option_state*); struct option_state*);
void delayed_ack_enqueue(struct lease *);
void commit_leases_readerdry(void *);
void flush_ackqueue(void *);
void dhcp_reply (struct lease *); void dhcp_reply (struct lease *);
int find_lease (struct lease **, struct packet *, int find_lease (struct lease **, struct packet *,
struct shared_network *, int *, int *, struct lease *, struct shared_network *, int *, int *, struct lease *,
@@ -2953,7 +2951,6 @@ isc_result_t write_named_billing_class(const void *, unsigned, void *);
void write_billing_classes (void); void write_billing_classes (void);
int write_billing_class (struct class *); int write_billing_class (struct class *);
void commit_leases_timeout (void *); void commit_leases_timeout (void *);
void commit_leases_readerdry(void *);
int commit_leases (void); int commit_leases (void);
int commit_leases_timed (void); int commit_leases_timed (void);
void db_startup (int); void db_startup (int);

View File

@@ -3,7 +3,7 @@
Persistent database management routines for DHCPD... */ Persistent database management routines for DHCPD... */
/* /*
* Copyright (c) 2012-2014 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 2012-2015 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC") * Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
* Copyright (c) 1995-2003 by Internet Software Consortium * Copyright (c) 1995-2003 by Internet Software Consortium
* *
@@ -1017,9 +1017,6 @@ int commit_leases ()
return (0); return (0);
} }
/* send out all deferred ACKs now */
flush_ackqueue(NULL);
/* If we haven't rewritten the lease database in over an /* If we haven't rewritten the lease database in over an
hour, rewrite it now. (The length of time should probably hour, rewrite it now. (The length of time should probably
be configurable. */ be configurable. */

View File

@@ -31,7 +31,6 @@
#include <limits.h> #include <limits.h>
#include <sys/time.h> #include <sys/time.h>
static void commit_leases_ackout(void *foo);
static void maybe_return_agent_options(struct packet *packet, static void maybe_return_agent_options(struct packet *packet,
struct option_state *options); struct option_state *options);
static int reuse_lease (struct packet* packet, struct lease* new_lease, static int reuse_lease (struct packet* packet, struct lease* new_lease,
@@ -40,6 +39,11 @@ static int reuse_lease (struct packet* packet, struct lease* new_lease,
int outstanding_pings; int outstanding_pings;
#if defined(DELAYED_ACK)
static void delayed_ack_enqueue(struct lease *);
static void delayed_acks_timer(void *);
struct leasequeue *ackqueue_head, *ackqueue_tail; struct leasequeue *ackqueue_head, *ackqueue_tail;
static struct leasequeue *free_ackqueue; static struct leasequeue *free_ackqueue;
static struct timeval max_fsync; static struct timeval max_fsync;
@@ -49,6 +53,7 @@ int max_outstanding_acks = DEFAULT_DELAYED_ACK;
int max_ack_delay_secs = DEFAULT_ACK_DELAY_SECS; int max_ack_delay_secs = DEFAULT_ACK_DELAY_SECS;
int max_ack_delay_usecs = DEFAULT_ACK_DELAY_USECS; int max_ack_delay_usecs = DEFAULT_ACK_DELAY_USECS;
int min_ack_delay_usecs = DEFAULT_MIN_ACK_DELAY_USECS; int min_ack_delay_usecs = DEFAULT_MIN_ACK_DELAY_USECS;
#endif
static char dhcp_message [256]; static char dhcp_message [256];
static int site_code_min; static int site_code_min;
@@ -3368,6 +3373,8 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
} }
} }
#if defined(DELAYED_ACK)
/* /*
* CC: queue single ACK: * CC: queue single ACK:
* - write the lease (but do not fsync it yet) * - write the lease (but do not fsync it yet)
@@ -3377,7 +3384,7 @@ void ack_lease (packet, lease, offer, when, msg, ms_nulltp, hp)
* but only up to the max timer value. * but only up to the max timer value.
*/ */
void static void
delayed_ack_enqueue(struct lease *lease) delayed_ack_enqueue(struct lease *lease)
{ {
struct leasequeue *q; struct leasequeue *q;
@@ -3405,11 +3412,9 @@ delayed_ack_enqueue(struct lease *lease)
outstanding_acks++; outstanding_acks++;
if (outstanding_acks > max_outstanding_acks) { if (outstanding_acks > max_outstanding_acks) {
commit_leases(); /* Cancel any pending timeout and call handler directly */
cancel_timeout(delayed_acks_timer, NULL);
/* Reset max_fsync and cancel any pending timeout. */ delayed_acks_timer(NULL);
memset(&max_fsync, 0, sizeof(max_fsync));
cancel_timeout(commit_leases_ackout, NULL);
} else { } else {
struct timeval next_fsync; struct timeval next_fsync;
@@ -3440,44 +3445,68 @@ delayed_ack_enqueue(struct lease *lease)
next_fsync.tv_usec = max_fsync.tv_usec; next_fsync.tv_usec = max_fsync.tv_usec;
} }
add_timeout(&next_fsync, commit_leases_ackout, NULL, add_timeout(&next_fsync, delayed_acks_timer, NULL,
(tvref_t) NULL, (tvunref_t) NULL); (tvref_t) NULL, (tvunref_t) NULL);
} }
} }
static void /* Processes any delayed acks:
commit_leases_ackout(void *foo) * Commits the leases and then for each delayed ack:
{ * - Update the failover peer if we're in failover
if (outstanding_acks) { * - Send the REPLY to the client
commit_leases();
memset(&max_fsync, 0, sizeof(max_fsync));
}
}
/* CC: process the delayed ACK responses:
- send out the ACK packets
- move the queue slots to the free list
*/ */
void static void
flush_ackqueue(void *foo) delayed_acks_timer(void *foo)
{ {
struct leasequeue *ack, *p; struct leasequeue *ack, *p;
/* Reset max fsync */
memset(&max_fsync, 0, sizeof(max_fsync));
if (!outstanding_acks) {
/* Nothing to do, so punt, shouldn't happen? */
return;
}
/* Commit the leases first */
commit_leases();
/* Now process the delayed ACKs
- update failover peer
- send out the ACK packets
- move the queue slots to the free list
*/
/* process from bottom to retain packet order */ /* process from bottom to retain packet order */
for (ack = ackqueue_tail ; ack ; ack = p) { for (ack = ackqueue_tail ; ack ; ack = p) {
p = ack->prev; p = ack->prev;
#if defined(FAILOVER_PROTOCOL)
/* If we're in failover we need to send any deferred
* bind updates as well as the replies */
if (ack->lease->pool) {
dhcp_failover_state_t *fpeer;
fpeer = ack->lease->pool->failover_peer;
if (fpeer && fpeer->link_to_peer) {
dhcp_failover_send_updates(fpeer);
}
}
#endif
/* dhcp_reply() requires that the reply state still be valid */ /* dhcp_reply() requires that the reply state still be valid */
if (ack->lease->state == NULL) if (ack->lease->state == NULL)
log_error("delayed ack for %s has gone stale", log_error("delayed ack for %s has gone stale",
piaddr(ack->lease->ip_addr)); piaddr(ack->lease->ip_addr));
else else {
dhcp_reply(ack->lease); dhcp_reply(ack->lease);
}
lease_dereference(&ack->lease, MDL); lease_dereference(&ack->lease, MDL);
ack->next = free_ackqueue; ack->next = free_ackqueue;
free_ackqueue = ack; free_ackqueue = ack;
} }
ackqueue_head = NULL; ackqueue_head = NULL;
ackqueue_tail = NULL; ackqueue_tail = NULL;
outstanding_acks = 0; outstanding_acks = 0;
@@ -3500,6 +3529,8 @@ relinquish_ackqueue(void)
} }
#endif #endif
#endif /* defined(DELAYED_ACK) */
void dhcp_reply (lease) void dhcp_reply (lease)
struct lease *lease; struct lease *lease;
{ {

View File

@@ -1059,7 +1059,8 @@ void postconf_initialization (int quiet)
data_string_forget(&db, MDL); data_string_forget(&db, MDL);
} }
} }
#if defined(DELAYED_ACK)
oc = lookup_option(&server_universe, options, SV_DELAYED_ACK); oc = lookup_option(&server_universe, options, SV_DELAYED_ACK);
if (oc && if (oc &&
evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL, evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
@@ -1087,6 +1088,7 @@ void postconf_initialization (int quiet)
data_string_forget(&db, MDL); data_string_forget(&db, MDL);
} }
#endif
oc = lookup_option(&server_universe, options, SV_DONT_USE_FSYNC); oc = lookup_option(&server_universe, options, SV_DONT_USE_FSYNC);
if ((oc != NULL) && if ((oc != NULL) &&