X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/968824e876d82e04c15782e4b8ef8a47ea152d13..1389d7b677b93bf774f2e1c9e362fd43b4727e44:/cluster.c diff --git a/cluster.c b/cluster.c index e3e7f01..29322fc 100644 --- a/cluster.c +++ b/cluster.c @@ -1,6 +1,6 @@ // L2TPNS Clustering Stuff -char const *cvs_id_cluster = "$Id: cluster.c,v 1.26.2.5 2005/05/02 09:03:27 bodea Exp $"; +char const *cvs_id_cluster = "$Id: cluster.c,v 1.26.2.8 2005/05/22 12:02:41 bodea Exp $"; #include #include @@ -354,9 +354,9 @@ static void send_heartbeat(int seq, char *data, int size) } // -// Send an 'i am alive' message to every machine in the cluster. +// Send an 'i am alive' message to every machine in the cluster, or to a single peer // -void cluster_send_ping(time_t basetime) +static void send_ping(time_t basetime, in_addr_t peer) { char buff[100 + sizeof(pingt)]; char *p = buff; @@ -365,15 +365,29 @@ void cluster_send_ping(time_t basetime) if (config->cluster_iam_master && basetime) // We're heartbeating so no need to ping. return; - LOG(5, 0, 0, "Sending cluster ping...\n"); - x.ver = 1; x.addr = config->bind_address; x.undef = config->cluster_undefined_sessions + config->cluster_undefined_tunnels; x.basetime = basetime; add_type(&p, C_PING, basetime, (char *) &x, sizeof(x)); - cluster_send_data(buff, (p-buff) ); + + if (peer) + peer_send_data(peer, buff, (p-buff)); + else + cluster_send_data(buff, (p-buff) ); +} + +void cluster_send_ping(time_t basetime) +{ + LOG(5, 0, 0, "Sending cluster ping...\n"); + send_ping(0, basetime); +} + +static void peer_send_ping(in_addr_t peer, time_t basetime) +{ + LOG(5, 0, 0, "Sending unicast ping to %s...\n", fmtaddr(peer, 0)); + send_ping(peer, basetime); } // @@ -485,14 +499,15 @@ void cluster_check_master(void) // If the master is late (missed 2 hearbeats by a second and a // hair) it may be that the switch has dropped us from the - // multicast group, try unicasting one probe to the master + // multicast group, try unicasting probes to the master // which will hopefully respond with a unicast heartbeat that // will allow us to limp along until the querier next runs. - if (TIME > (config->cluster_last_hb + 2 * config->cluster_hb_interval + 11)) + if (config->cluster_master_address + && TIME > (config->cluster_last_hb + 2 * config->cluster_hb_interval + 11)) { - if (!probed && config->cluster_master_address) + if (!probed || (TIME > (probed + 2 * config->cluster_hb_interval))) { - probed = 1; + probed = TIME; LOG(1, 0, 0, "Heartbeat from master %.1fs late, probing...\n", 0.1 * (TIME - (config->cluster_last_hb + config->cluster_hb_interval))); @@ -621,6 +636,11 @@ void cluster_check_master(void) if (!num_peers) // lone master advertise(); +#ifdef BGP + else if (bgp_configured) + bgp_enable_routing(0); +#endif /* BGP */ + // FIXME. We need to fix up the tunnel control message // queue here! There's a number of other variables we @@ -896,6 +916,12 @@ static int cluster_catchup_slave(int seq, in_addr_t slave) int diff; LOG(1, 0, 0, "Slave %s sent LASTSEEN with seq %d\n", fmtaddr(slave, 0), seq); + if (!config->cluster_iam_master) { + LOG(1, 0, 0, "Got LASTSEEN but I'm not a master! Sending a PING.\n"); + // Send a ping to the slave so they know we're no longer a master + peer_send_ping(slave, basetime); + return 0; + } diff = config->cluster_seq_number - seq; // How many packet do we need to send? if (diff < 0) @@ -907,9 +933,11 @@ static int cluster_catchup_slave(int seq, in_addr_t slave) return peer_send_message(slave, C_KILL, seq, NULL, 0);// Kill the slave. Nothing else to do. } + LOG(1, 0, 0, "Sending %d catchup packets to slave %s\n", diff, fmtaddr(slave, 0) ); + // Now resend every packet that it missed, in order. while (seq != config->cluster_seq_number) { - s = seq%HB_HISTORY_SIZE; + s = seq % HB_HISTORY_SIZE; if (seq != past_hearts[s].seq) { LOG(0, 0, 0, "Tried to re-send heartbeat for %s but %d doesn't match %d! (%d,%d)\n", fmtaddr(slave, 0), seq, past_hearts[s].seq, s, config->cluster_seq_number); @@ -962,8 +990,10 @@ static int cluster_add_peer(in_addr_t peer, time_t basetime, pingt *pp, int size } // Is this the master shutting down?? - if (peer == config->cluster_master_address && !basetime) { - LOG(3, 0, 0, "Master %s shutting down...\n", fmtaddr(config->cluster_master_address, 0)); + if (peer == config->cluster_master_address) { + LOG(3, 0, 0, "Master %s %s\n", fmtaddr(config->cluster_master_address, 0), + basetime ? "has restarted!" : "shutting down..."); + config->cluster_master_address = 0; config->cluster_last_hb = 0; // Force an election. cluster_check_master(); @@ -1174,9 +1204,33 @@ static int cluster_process_heartbeat(uint8_t *data, int size, int more, uint8_t exit(1); } + // + // Send it a unicast heartbeat to see give it a chance to die. + // NOTE: It's actually safe to do seq-number - 1 without checking + // for wrap around. + // + cluster_catchup_slave(config->cluster_seq_number - 1, addr); + return -1; // Skip it. } + // + // Try and guard against a stray master appearing. + // + // Ignore heartbeats received from another master before the + // timeout (less a smidgen) for the old master has elapsed. + // + // Note that after a clean failover, the cluster_master_address + // is cleared, so this doesn't run. + // + if (config->cluster_master_address && addr != config->cluster_master_address + && (config->cluster_last_hb + config->cluster_hb_timeout - 11) > TIME) { + LOG(0, 0, 0, "Ignoring stray heartbeat from %s, current master %s has not yet timed out (last heartbeat %.1f seconds ago).\n", + fmtaddr(addr, 0), fmtaddr(config->cluster_master_address, 1), + 0.1 * (TIME - config->cluster_last_hb)); + return -1; // ignore + } + if (config->cluster_seq_number == -1) // Don't have one. Just align to the master... config->cluster_seq_number = h->seq;