// L2TPNS Clustering Stuff
-char const *cvs_id_cluster = "$Id: cluster.c,v 1.25 2004-12-16 08:49:53 bodea Exp $";
+char const *cvs_id_cluster = "$Id: cluster.c,v 1.29 2005-01-13 07:57:35 bodea Exp $";
#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <inttypes.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <string.h>
#include <malloc.h>
#include <errno.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <stdio.h>
#include <libcli.h>
-#include <inttypes.h>
#include "l2tpns.h"
#include "cluster.h"
*/
// Module variables.
-int cluster_sockfd = 0; // The filedescriptor for the cluster communications port.
+int cluster_sockfd = 0; // The filedescriptor for the cluster communications port.
in_addr_t my_address = 0; // The network address of my ethernet port.
static int walk_session_number = 0; // The next session to send when doing the slow table walk.
static int walk_tunnel_number = 0; // The next tunnel to send when doing the slow table walk.
+int forked = 0; // Sanity check: CLI must not diddle with heartbeat table
#define MAX_HEART_SIZE (8192) // Maximum size of heartbeat packet. Must be less than max IP packet size :)
#define MAX_CHANGES (MAX_HEART_SIZE/(sizeof(sessiont) + sizeof(int) ) - 2) // Assumes a session is the biggest type!
static struct {
in_addr_t peer;
- time_t basetime;
+ uint32_t basetime;
clockt timestamp;
int uptodate;
} peers[CLUSTER_MAX_SIZE]; // List of all the peers we've heard from.
if ( walk_session_number > config->cluster_highest_sessionid)
walk_session_number = 1;
- if (!sess_count[walk_session_number].cin && !sess_count[walk_session_number].cout)
+ if (!sess_local[walk_session_number].cin && !sess_local[walk_session_number].cout)
continue; // Unused. Skip it.
b[c].sid = walk_session_number;
- b[c].in = sess_count[walk_session_number].cin;
- b[c].out = sess_count[walk_session_number].cout;
+ b[c].in = sess_local[walk_session_number].cin;
+ b[c].out = sess_local[walk_session_number].cout;
if (++c > MAX_B_RECS) // Send a max of 400 elements in a packet.
break;
// Reset counters.
- sess_count[walk_session_number].cin = sess_count[walk_session_number].cout = 0;
+ sess_local[walk_session_number].cin = sess_local[walk_session_number].cout = 0;
}
if (!c) // Didn't find any that changes. Get out of here!
session[i].last_packet = time_now;
// Accumulate un-sent byte counters.
- session[i].cin += sess_count[i].cin;
- session[i].cout += sess_count[i].cout;
- session[i].total_cin += sess_count[i].cin;
- session[i].total_cout += sess_count[i].cout;
+ session[i].cin += sess_local[i].cin;
+ session[i].cout += sess_local[i].cout;
+ session[i].total_cin += sess_local[i].cin;
+ session[i].total_cout += sess_local[i].cout;
- sess_count[i].cin = sess_count[i].cout = 0;
+ sess_local[i].cin = sess_local[i].cout = 0;
session[i].radius = 0; // Reset authentication as the radius blocks aren't up to date.
return -1;
}
+ if (forked) {
+ LOG(0, sid, 0, "cluster_send_session called from child process!\n");
+ return -1;
+ }
+
return type_changed(C_CSESSION, sid);
}
config->cluster_last_hb = TIME; // Reset to ensure that we don't become master!!
if (config->cluster_seq_number != h->seq) { // Out of sequence heartbeat!
- LOG(1, 0, 0, "HB: Got seq# %d but was expecting %d. asking for resend.\n", h->seq, config->cluster_seq_number);
+ static int lastseen_seq = 0;
+ static time_t lastseen_time = 0;
- peer_send_message(addr, C_LASTSEEN, config->cluster_seq_number, NULL, 0);
+ // limit to once per second for a particular seq#
+ int ask = (config->cluster_seq_number != lastseen_seq || time_now != lastseen_time);
+
+ LOG(1, 0, 0, "HB: Got seq# %d but was expecting %d. %s.\n",
+ h->seq, config->cluster_seq_number,
+ ask ? "Asking for resend" : "Ignoring");
+
+ if (ask)
+ {
+ lastseen_seq = config->cluster_seq_number;
+ lastseen_time = time_now;
+ peer_send_message(addr, C_LASTSEEN, config->cluster_seq_number, NULL, 0);
+ }
config->cluster_last_hb = TIME; // Reset to ensure that we don't become master!!
: "Not defined",
0.1 * (TIME - config->cluster_last_hb));
cli_print(cli, "Uptodate : %s", config->cluster_iam_uptodate ? "Yes" : "No");
- cli_print(cli, "Table version # : %llu", config->cluster_table_version);
+ cli_print(cli, "Table version # : %" PRIu64, config->cluster_table_version);
cli_print(cli, "Next sequence number expected: %d", config->cluster_seq_number);
cli_print(cli, "%d sessions undefined of %d", config->cluster_undefined_sessions, config->cluster_highest_sessionid);
cli_print(cli, "%d tunnels undefined of %d", config->cluster_undefined_tunnels, config->cluster_highest_tunnelid);
} else {
- cli_print(cli, "Table version # : %llu", config->cluster_table_version);
+ cli_print(cli, "Table version # : %" PRIu64, config->cluster_table_version);
cli_print(cli, "Next heartbeat # : %d", config->cluster_seq_number);
cli_print(cli, "Highest session : %d", config->cluster_highest_sessionid);
cli_print(cli, "Highest tunnel : %d", config->cluster_highest_tunnelid);
if (num_peers)
cli_print(cli, "%20s %10s %8s", "Address", "Basetime", "Age");
for (i = 0; i < num_peers; ++i) {
- cli_print(cli, "%20s %10d %8d", fmtaddr(peers[i].peer, 0),
+ cli_print(cli, "%20s %10u %8d", fmtaddr(peers[i].peer, 0),
peers[i].basetime, TIME - peers[i].timestamp);
}
return CLI_OK;