]> git.ipfire.org Git - thirdparty/dhcp.git/commitdiff
[master] Delayed-ack now works correctly with failover
authorThomas Markwalder <tmark@isc.org>
Mon, 15 Jun 2015 19:19:42 +0000 (15:19 -0400)
committerThomas Markwalder <tmark@isc.org>
Mon, 15 Jun 2015 19:19:42 +0000 (15:19 -0400)
    Merges in 31474.

RELNOTES
includes/dhcpd.h
server/db.c
server/dhcp.c
server/dhcpd.c

index a7027019535dd22868b38ef4b2e396b435961e46..b6daddf923357938c83648707daf76cd11144a74 100644 (file)
--- a/RELNOTES
+++ b/RELNOTES
@@ -54,6 +54,11 @@ by Eric Young (eay@cryptsoft.com).
 
                        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
   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
index 2a43229f202fc84702d35e72a5842b7790b82a10..378459b9d5fb5f0a0e3bb27e77b002349cbdce55 100644 (file)
@@ -2313,9 +2313,7 @@ void ack_lease (struct packet *, struct lease *,
                unsigned int, TIME, char *, int, struct host_decl *);
 void echo_client_id(struct packet*, struct lease*, 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 *);
 int find_lease (struct lease **, struct packet *,
                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);
 int write_billing_class (struct class *);
 void commit_leases_timeout (void *);
-void commit_leases_readerdry(void *);
 int commit_leases (void);
 int commit_leases_timed (void);
 void db_startup (int);
index e1f1beb759f8c70bc0f1096e982b0ef798cf3b7a..d4d42feb911bf2365feb9491c360143ec46e2551 100644 (file)
@@ -3,7 +3,7 @@
    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) 1995-2003 by Internet Software Consortium
  *
@@ -1017,9 +1017,6 @@ int commit_leases ()
                return (0);
        }
 
-       /* send out all deferred ACKs now */
-       flush_ackqueue(NULL);
-
        /* If we haven't rewritten the lease database in over an
           hour, rewrite it now.  (The length of time should probably
           be configurable. */
index e71720f6313eb76520c402bfb7bdd16f56db66cb..ba32c5b42f605dd300df002f7df97dfad1f02ea6 100644 (file)
@@ -31,7 +31,6 @@
 #include <limits.h>
 #include <sys/time.h>
 
-static void commit_leases_ackout(void *foo);
 static void maybe_return_agent_options(struct packet *packet,
                                       struct option_state *options);
 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;
 
+#if defined(DELAYED_ACK)
+static void delayed_ack_enqueue(struct lease *);
+static void delayed_acks_timer(void *);
+
+
 struct leasequeue *ackqueue_head, *ackqueue_tail;
 static struct leasequeue *free_ackqueue;
 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_usecs = DEFAULT_ACK_DELAY_USECS;
 int min_ack_delay_usecs = DEFAULT_MIN_ACK_DELAY_USECS;
+#endif
 
 static char dhcp_message [256];
 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:
  * - 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.
  */
 
-void
+static void
 delayed_ack_enqueue(struct lease *lease)
 {
        struct leasequeue *q;
@@ -3405,11 +3412,9 @@ delayed_ack_enqueue(struct lease *lease)
 
        outstanding_acks++;
        if (outstanding_acks > max_outstanding_acks) {
-               commit_leases();
-
-               /* Reset max_fsync and cancel any pending timeout. */
-               memset(&max_fsync, 0, sizeof(max_fsync));
-               cancel_timeout(commit_leases_ackout, NULL);
+               /* Cancel any pending timeout and call handler directly */
+               cancel_timeout(delayed_acks_timer, NULL);
+               delayed_acks_timer(NULL);
        } else {
                struct timeval next_fsync;
 
@@ -3440,44 +3445,68 @@ delayed_ack_enqueue(struct lease *lease)
                        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);
        }
 }
 
+/* Processes any delayed acks:
+ * Commits the leases and then for each delayed ack:
+ *  - Update the failover peer if we're in failover
+ *  - Send the REPLY to the client
+ */
 static void
-commit_leases_ackout(void *foo)
+delayed_acks_timer(void *foo)
 {
-       if (outstanding_acks) {
-               commit_leases();
+       struct leasequeue *ack, *p;
+
+       /* Reset max fsync */
+       memset(&max_fsync, 0, sizeof(max_fsync));
 
-               memset(&max_fsync, 0, sizeof(max_fsync));
+       if (!outstanding_acks) {
+               /* Nothing to do, so punt, shouldn't happen? */
+               return;
        }
-}
 
-/* CC: process the delayed ACK responses:
-   - send out the ACK packets
-   - move the queue slots to the free list
- */
-void
-flush_ackqueue(void *foo) 
-{
-       struct leasequeue *ack, *p;
+       /* 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 */
        for (ack = ackqueue_tail ; ack ; ack = p) { 
                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 */
                if (ack->lease->state == NULL)
                        log_error("delayed ack for %s has gone stale",
                                  piaddr(ack->lease->ip_addr));
-               else
+               else {
                        dhcp_reply(ack->lease);
+               }
 
                lease_dereference(&ack->lease, MDL);
                ack->next = free_ackqueue;
                free_ackqueue = ack;
        }
+
        ackqueue_head = NULL;
        ackqueue_tail = NULL;
        outstanding_acks = 0;
@@ -3500,6 +3529,8 @@ relinquish_ackqueue(void)
 }
 #endif
 
+#endif /* defined(DELAYED_ACK) */
+
 void dhcp_reply (lease)
        struct lease *lease;
 {
index cb4f01127268e8df9a48917ac8948f9c84a42b53..ebb6d3e333215fcac6941350b0271f1b649feaf4 100644 (file)
@@ -1059,7 +1059,8 @@ void postconf_initialization (int quiet)
                        data_string_forget(&db, MDL);
                }
        }
-       
+
+#if defined(DELAYED_ACK)
        oc = lookup_option(&server_universe, options, SV_DELAYED_ACK);
        if (oc &&
            evaluate_option_cache(&db, NULL, NULL, NULL, options, NULL,
@@ -1087,6 +1088,7 @@ void postconf_initialization (int quiet)
 
                data_string_forget(&db, MDL);
        }
+#endif
 
        oc = lookup_option(&server_universe, options, SV_DONT_USE_FSYNC);
        if ((oc != NULL) &&