📄 failover.c
字号:
#endif dhcp_failover_send_state (state); if (link -> imsg -> options_present & FTB_MAX_UNACKED) state -> partner.max_flying_updates = link -> imsg -> max_unacked; if (link -> imsg -> options_present & FTB_RECEIVE_TIMER) state -> partner.max_response_delay = link -> imsg -> receive_timer;#if defined (DEBUG_FAILOVER_TIMING) log_info ("add_timeout +%d %s", (int)state -> partner.max_response_delay / 3, "dhcp_failover_send_contact");#endif add_timeout (cur_time + (int)state -> partner.max_response_delay / 3, dhcp_failover_send_contact, state, (tvref_t)dhcp_failover_state_reference, (tvunref_t)dhcp_failover_state_dereference);#if defined (DEBUG_FAILOVER_TIMING) log_info ("add_timeout +%d %s", (int)state -> me.max_response_delay, "dhcp_failover_timeout");#endif add_timeout (cur_time + (int)state -> me.max_response_delay, dhcp_failover_timeout, state, (tvref_t)dhcp_failover_state_reference, (tvunref_t)dhcp_failover_state_dereference); } else if (link -> imsg -> type == FTM_DISCONNECT) { if (link -> imsg -> reject_reason) { log_error ("Failover DISCONNECT from %u.%u.%u.%u%s%s", ((u_int8_t *) (&link -> imsg -> server_addr)) [0], ((u_int8_t *) (&link -> imsg -> server_addr)) [1], ((u_int8_t *) (&link -> imsg -> server_addr)) [2], ((u_int8_t *) (&link -> imsg -> server_addr)) [3], ": ", (dhcp_failover_reject_reason_print (link -> imsg -> reject_reason))); } omapi_disconnect (link -> outer, 1); } else if (link -> imsg -> type == FTM_BNDUPD) { dhcp_failover_process_bind_update (state, link -> imsg); } else if (link -> imsg -> type == FTM_BNDACK) { dhcp_failover_process_bind_ack (state, link -> imsg); } else if (link -> imsg -> type == FTM_UPDREQ) { dhcp_failover_process_update_request (state, link -> imsg); } else if (link -> imsg -> type == FTM_UPDREQALL) { dhcp_failover_process_update_request_all (state, link -> imsg); } else if (link -> imsg -> type == FTM_UPDDONE) { dhcp_failover_process_update_done (state, link -> imsg); } else if (link -> imsg -> type == FTM_POOLREQ) { dhcp_failover_pool_rebalance (state); } else if (link -> imsg -> type == FTM_POOLRESP) { log_info ("pool response: %ld leases", (unsigned long) link -> imsg -> addresses_transferred); } else if (link -> imsg -> type == FTM_STATE) { dhcp_failover_peer_state_changed (state, link -> imsg); } /* Add a timeout so that if the partner doesn't send another message for the maximum transmit idle time plus a grace of one second, we close the connection. */ if (state -> link_to_peer && state -> link_to_peer == link && state -> link_to_peer -> state != dhcp_flink_disconnected) {#if defined (DEBUG_FAILOVER_TIMING) log_info ("add_timeout +%d %s", (int)state -> me.max_response_delay, "dhcp_failover_timeout");#endif add_timeout (cur_time + (int)state -> me.max_response_delay, dhcp_failover_timeout, state, (tvref_t)dhcp_failover_state_reference, (tvunref_t)dhcp_failover_state_dereference); } } /* Handle all the events we care about... */ return ISC_R_SUCCESS;}isc_result_t dhcp_failover_state_transition (dhcp_failover_state_t *state, const char *name){ isc_result_t status; /* XXX Check these state transitions against the spec! */ if (!strcmp (name, "disconnect")) { if (state -> link_to_peer) { log_info ("peer %s: disconnected", state -> name); if (state -> link_to_peer -> state_object) dhcp_failover_state_dereference (&state -> link_to_peer -> state_object, MDL); dhcp_failover_link_dereference (&state -> link_to_peer, MDL); } cancel_timeout (dhcp_failover_send_contact, state); cancel_timeout (dhcp_failover_timeout, state); cancel_timeout (dhcp_failover_startup_timeout, state); switch (state -> me.state == startup ? state -> saved_state : state -> me.state) { case resolution_interrupted: case partner_down: case communications_interrupted: case recover: /* Already in the right state? */ if (state -> me.state == startup) return (dhcp_failover_set_state (state, state -> saved_state)); return ISC_R_SUCCESS; case potential_conflict: return dhcp_failover_set_state (state, resolution_interrupted); case normal: return dhcp_failover_set_state (state, communications_interrupted); case unknown_state: return dhcp_failover_set_state (state, resolution_interrupted); case startup: break; /* can't happen. */ } } else if (!strcmp (name, "connect")) { switch (state -> me.state) { case communications_interrupted: status = dhcp_failover_set_state (state, normal); dhcp_failover_send_updates (state); return status; case resolution_interrupted: return dhcp_failover_set_state (state, potential_conflict); case partner_down: case potential_conflict: case normal: case recover: case shut_down: case paused: case unknown_state: case recover_done: case startup: case recover_wait: return dhcp_failover_send_state (state); } } else if (!strcmp (name, "startup")) { dhcp_failover_set_state (state, startup); return ISC_R_SUCCESS; } else if (!strcmp (name, "connect-timeout")) { switch (state -> me.state) { case communications_interrupted: case partner_down: case resolution_interrupted: return ISC_R_SUCCESS; case normal: case recover: return dhcp_failover_set_state (state, communications_interrupted); case potential_conflict: return dhcp_failover_set_state (state, resolution_interrupted); case unknown_state: return dhcp_failover_set_state (state, communications_interrupted); default: return dhcp_failover_set_state (state, resolution_interrupted); } } return ISC_R_INVALIDARG;}isc_result_t dhcp_failover_set_service_state (dhcp_failover_state_t *state){ switch (state -> me.state) { case unknown_state: state -> service_state = not_responding; state -> nrr = " (my state unknown)"; break; case partner_down: state -> service_state = service_partner_down; state -> nrr = ""; break; case normal: state -> service_state = cooperating; state -> nrr = ""; break; case communications_interrupted: state -> service_state = not_cooperating; state -> nrr = ""; break; case resolution_interrupted: case potential_conflict: state -> service_state = not_responding; state -> nrr = " (resolving conflicts)"; break; case recover: state -> service_state = not_responding; state -> nrr = " (recovering)"; break; case shut_down: state -> service_state = not_responding; state -> nrr = " (shut down)"; break; case paused: state -> service_state = not_responding; state -> nrr = " (paused)"; break; case recover_wait: state -> service_state = not_responding; state -> nrr = " (recover wait)"; break; case recover_done: state -> service_state = not_responding; state -> nrr = " (recover done)"; break; case startup: state -> service_state = service_startup; state -> nrr = " (startup)"; break; } /* Some peer states can require us not to respond, even if our state doesn't. */ /* XXX hm. I suspect this isn't true anymore. */ if (state -> service_state != not_responding) { switch (state -> partner.state) { case partner_down: state -> service_state = not_responding; state -> nrr = " (recovering)"; break; case potential_conflict: state -> service_state = not_responding; state -> nrr = " (resolving conflicts)"; break; /* Other peer states don't affect our behaviour. */ default: break; } } return ISC_R_SUCCESS;}isc_result_t dhcp_failover_set_state (dhcp_failover_state_t *state, enum failover_state new_state){ enum failover_state saved_state; TIME saved_stos; struct pool *p; struct shared_network *s; struct lease *l; /* First make the transition out of the current state. */ switch (state -> me.state) { case normal: /* Any updates that haven't been acked yet, we have to resend, just in case. */ if (state -> ack_queue_tail) { struct lease *lp; /* Zap the flags. */ for (lp = state -> ack_queue_head; lp; lp = lp -> next_pending) lp -> flags = ((lp -> flags & ~ON_ACK_QUEUE) | ON_UPDATE_QUEUE); /* Now hook the ack queue to the beginning of the update queue. */ if (state -> update_queue_head) { lease_reference (&state -> ack_queue_tail -> next_pending, state -> update_queue_head, MDL); lease_dereference (&state -> update_queue_head, MDL); } lease_reference (&state -> update_queue_head, state -> ack_queue_head, MDL); if (!state -> update_queue_tail) {#if defined (POINTER_DEBUG) if (state -> ack_queue_tail -> next_pending) { log_error ("next pending on ack queue tail."); abort (); }#endif lease_reference (&state -> update_queue_tail, state -> ack_queue_tail, MDL); } lease_dereference (&state -> ack_queue_tail, MDL); lease_dereference (&state -> ack_queue_head, MDL); state -> cur_unacked_updates = 0; } cancel_timeout (dhcp_failover_keepalive, state); break; case recover: case recover_wait: case recover_done: case potential_conflict: case partner_down: case communications_interrupted: case resolution_interrupted: case startup: default: break; } /* Tentatively make the transition. */ saved_state = state -> me.state; saved_stos = state -> me.stos; /* Keep the old stos if we're going into recover_wait or if we're coming into or out of startup. */ if (new_state != recover_wait && new_state != startup && saved_state != startup) state -> me.stos = cur_time; /* If we're in shutdown, peer is in partner_down, and we're moving to recover, we can skip waiting for MCLT to expire. This happens when a server is moved administratively into shutdown prior to actually shutting down. Of course, if there are any updates pending we can't actually do this. */ if (new_state == recover && saved_state == shut_down && state -> partner.state == partner_down && !state -> update_queue_head && !state -> ack_queue_head) state -> me.stos = cur_time - state -> mclt; state -> me.state = new_state; if (new_state == startup && saved_state != startup) state -> saved_state = saved_state; /* If we can't record the new state, we can't make a state transition. */ if (!write_failover_state (state) || !commit_leases ()) { log_error ("Unable to record current failover state for %s", state -> name); state -> me.state = saved_state; state -> me.stos = saved_stos; return ISC_R_IOERROR; } log_info ("failover peer %s: I move from %s to %s", state -> name, dhcp_failover_state_name_print (saved_state), dhcp_failover_state_name_print (state -> me.state)); /* If we were in startup and we just left it, cancel the timeout. */ if (new_state != startup && saved_state == startup) cancel_timeout (dhcp_failover_startup_timeout, state); /* Set our service state. */ dhcp_failover_set_service_state (state); /* Tell the peer about it. */ if (state -> link_to_peer) dhcp_failover_send_state (state); switch (new_state) { case normal: if (state -> partner.state == normal) dhcp_failover_state_pool_check (state); break; case potential_conflict: if (state -> i_am == primary) dhcp_failover_send_update_request (state); break; case startup:#if defined (DEBUG_FAILOVER_TIMING) log_info ("add_timeout +15 %s", "dhcp_failover_startup_timeout");#endif add_timeout (cur_time + 15, dhcp_failover_startup_timeout, state, (tvref_t)omapi_object_reference, (tvunref_t) omapi_object_dereference); break; /* If we come back in recover_wait and there's still waiting to do, set a timeout. */ case recover_wait: if (state -> me.stos + state -> mclt > cur_time) {#if defined (DEBUG_FAILOVER_TIMING) log_info ("add_timeout +%d %s", (int)(cur_time - state -> me.stos + state -> mclt), "dhcp_failover_startup_timeout");#endif add_timeout ((int)(state -> me.stos + state -> mclt), dhcp_failover_recover_done, state, (tvref_t)omapi_object_reference, (tvunref_t) omapi_object_dereference); } else dhcp_failover_recover_done (state); break; case recover: if (state -> link_to_peer) dhcp_failover_send_update_request_all (state); break; case partner_down: /* For every expired lease, set a timeout for it to become free. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -