X-Git-Url: http://git.sameswireless.fr/l2tpns.git/blobdiff_plain/a350423d38f12d40b50a2d253ef2516d4409c2bc..aa77d4f89aa291e851c9be8a64ecfdb1434e83c9:/l2tpns.c diff --git a/l2tpns.c b/l2tpns.c index eb95d57..e9f768a 100644 --- a/l2tpns.c +++ b/l2tpns.c @@ -4,7 +4,7 @@ // Copyright (c) 2002 FireBrick (Andrews & Arnold Ltd / Watchfront Ltd) - GPL licenced // vim: sw=8 ts=8 -char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.73.2.12 2005/05/30 06:35:19 bodea Exp $"; +char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.73.2.17 2005/07/03 02:40:22 bodea Exp $"; #include #include @@ -112,6 +112,7 @@ config_descriptt config_values[] = { CONFIG("accounting_dir", accounting_dir, STRING), CONFIG("setuid", target_uid, INT), CONFIG("dump_speed", dump_speed, BOOL), + CONFIG("cleanup_interval", cleanup_interval, INT), CONFIG("multi_read_count", multi_read_count, INT), CONFIG("scheduler_fifo", scheduler_fifo, BOOL), CONFIG("lock_pages", lock_pages, BOOL), @@ -2061,64 +2062,42 @@ static void processtun(uint8_t * buf, int len) // Else discard. } -// Handle retries, timeouts. Runs every 1/10th sec, want to ensure -// that we look at the whole of the tunnel, radius and session tables -// every second -static void regular_cleanups(int period) -{ - // Next tunnel, radius and session to check for actions on. - static tunnelidt t = 0; - static int r = 0; - static sessionidt s = 0; - - int t_actions = 0; - int r_actions = 0; - int s_actions = 0; - - int t_slice; - int r_slice; - int s_slice; +// +// Maximum number of actions to complete. +// This is to avoid sending out too many packets +// at once. +#define MAX_ACTIONS 500 - int i; +static int regular_cleanups(void) +{ + static sessionidt s = 0; // Next session to check for actions on. + tunnelidt t; + int count=0,i; + uint16_t r; + static clockt next_acct = 0; + static clockt next_shut_acct = 0; int a; - // paranoia - if (period < 1) period = 1; - - // divide up tables into period * 1/10th sec slices - t_slice = config->cluster_highest_tunnelid / 10.0 * period + 0.5; - r_slice = (MAXRADIUS - 1) / 10.0 * period + 0.5; - s_slice = config->cluster_highest_sessionid / 10.0 * period + 0.5; - - if (t_slice < 1) - t_slice = 1; - else if (t_slice > config->cluster_highest_tunnelid) - t_slice = config->cluster_highest_tunnelid; - - if (r_slice < 1) - r_slice = 1; - else if (r_slice > (MAXRADIUS - 1)) - r_slice = MAXRADIUS - 1; - - if (s_slice < 1) - s_slice = 1; - else if (s_slice > config->cluster_highest_sessionid) - s_slice = config->cluster_highest_sessionid; - - LOG(4, 0, 0, "Begin regular cleanup (last %d/10s ago)\n", period); + LOG(3, 0, 0, "Begin regular cleanup\n"); - for (i = 0; i < t_slice; i++) + for (r = 1; r < MAXRADIUS; r++) + { + if (!radius[r].state) + continue; + if (radius[r].retry) + { + if (radius[r].retry <= TIME) + radiusretry(r); + } else + radius[r].retry = backoff(radius[r].try+1); // Is this really needed? --mo + } + for (t = 1; t <= config->cluster_highest_tunnelid; t++) { - t++; - if (t > config->cluster_highest_tunnelid) - t = 1; - // check for expired tunnels if (tunnel[t].die && tunnel[t].die <= TIME) { STAT(tunnel_timeout); tunnelkill(t, "Expired"); - t_actions++; continue; } // check for message resend @@ -2138,8 +2117,6 @@ static void regular_cleanups(int period) tunnelsend(c->buf, c->length, t); c = c->next; } - - t_actions++; } } // Send hello @@ -2148,7 +2125,6 @@ static void regular_cleanups(int period) controlt *c = controlnew(6); // sending HELLO controladd(c, t, 0); // send the message LOG(3, 0, t, "Sending HELLO message\n"); - t_actions++; } // Check for tunnel changes requested from the CLI @@ -2159,28 +2135,13 @@ static void regular_cleanups(int period) { LOG(2, 0, t, "Dropping tunnel by CLI\n"); tunnelshutdown(t, "Requested by administrator"); - t_actions++; } } - } - - for (i = 0; i < r_slice; i++) - { - r++; - if (r >= MAXRADIUS) - r = 1; - - if (!radius[r].state) - continue; - if (radius[r].retry <= TIME) - { - radiusretry(r); - r_actions++; - } } - for (i = 0; i < s_slice; i++) + count = 0; + for (i = 1; i <= config->cluster_highest_sessionid; i++) { s++; if (s > config->cluster_highest_sessionid) @@ -2194,14 +2155,13 @@ static void regular_cleanups(int period) // IPCP has not completed yet. Resend LOG(3, s, session[s].tunnel, "No ACK for initial IPCP ConfigReq... resending\n"); sendipcp(session[s].tunnel, s); - s_actions++; } // check for expired sessions if (session[s].die && session[s].die <= TIME) { sessionkill(s, "Expired"); - s_actions++; + if (++count >= MAX_ACTIONS) break; continue; } @@ -2210,7 +2170,7 @@ static void regular_cleanups(int period) { sessionshutdown(s, "No response to LCP ECHO requests"); STAT(session_timeout); - s_actions++; + if (++count >= MAX_ACTIONS) break; continue; } @@ -2230,7 +2190,7 @@ static void regular_cleanups(int period) LOG(4, s, session[s].tunnel, "No data in %d seconds, sending LCP ECHO\n", (int)(time_now - session[s].last_packet)); tunnelsend(b, 24, session[s].tunnel); // send it - s_actions++; + if (++count >= MAX_ACTIONS) break; } // Check for actions requested from the CLI @@ -2244,7 +2204,6 @@ static void regular_cleanups(int period) LOG(2, s, session[s].tunnel, "Dropping session by CLI\n"); sessionshutdown(s, "Requested by administrator"); a = 0; // dead, no need to check for other actions - s_actions++; } if (a & CLI_SESS_NOSNOOP) @@ -2252,7 +2211,6 @@ static void regular_cleanups(int period) LOG(2, s, session[s].tunnel, "Unsnooping session by CLI\n"); session[s].snoop_ip = 0; session[s].snoop_port = 0; - s_actions++; send++; } else if (a & CLI_SESS_SNOOP) @@ -2263,7 +2221,6 @@ static void regular_cleanups(int period) session[s].snoop_ip = cli_session_actions[s].snoop_ip; session[s].snoop_port = cli_session_actions[s].snoop_port; - s_actions++; send++; } @@ -2271,7 +2228,6 @@ static void regular_cleanups(int period) { LOG(2, s, session[s].tunnel, "Un-throttling session by CLI\n"); throttle_session(s, 0, 0); - s_actions++; send++; } else if (a & CLI_SESS_THROTTLE) @@ -2281,7 +2237,6 @@ static void regular_cleanups(int period) cli_session_actions[s].throttle_out); throttle_session(s, cli_session_actions[s].throttle_in, cli_session_actions[s].throttle_out); - s_actions++; send++; } @@ -2289,7 +2244,6 @@ static void regular_cleanups(int period) { LOG(2, s, session[s].tunnel, "Un-filtering session by CLI\n"); filter_session(s, 0, 0); - s_actions++; send++; } else if (a & CLI_SESS_FILTER) @@ -2299,17 +2253,39 @@ static void regular_cleanups(int period) cli_session_actions[s].filter_out); filter_session(s, cli_session_actions[s].filter_in, cli_session_actions[s].filter_out); - s_actions++; send++; } if (send) cluster_send_session(s); + + if (++count >= MAX_ACTIONS) break; } } - LOG(3, 0, 0, "End regular cleanup: scanned %d/%d/%d tunnels/radius/sessions, %d/%d/%d actions\n", - t_slice, r_slice, s_slice, t_actions, r_actions, s_actions); + if (*config->accounting_dir) + { + if (next_acct <= TIME) + { + // Dump accounting data + next_acct = TIME + ACCT_TIME; + next_shut_acct = TIME + ACCT_SHUT_TIME; + dump_acct_info(1); + } + else if (next_shut_acct <= TIME) + { + // Dump accounting data for shutdown sessions + next_shut_acct = TIME + ACCT_SHUT_TIME; + if (shut_acct_n) + dump_acct_info(0); + } + } + + if (count >= MAX_ACTIONS) + return 1; // Didn't finish! + + LOG(3, 0, 0, "End regular cleanup (%d actions), next in %d seconds\n", count, config->cleanup_interval); + return 0; } @@ -2404,6 +2380,7 @@ static void mainloop(void) uint8_t buf[65536]; struct timeval to; clockt next_cluster_ping = 0; // send initial ping immediately + time_t next_clean = time_now + config->cleanup_interval; LOG(4, 0, 0, "Beginning of main loop. udpfd=%d, tunfd=%d, cluster_sockfd=%d, controlfd=%d\n", udpfd, tunfd, cluster_sockfd, controlfd); @@ -2594,8 +2571,6 @@ static void mainloop(void) STAT(multi_read_exceeded); } - - TIME = now(); } // Runs on every machine (master and slaves). @@ -2611,60 +2586,38 @@ static void mainloop(void) master_update_counts(); // If we're a slave, send our byte counters to our master. - TIME = now(); if (config->cluster_iam_master && !config->cluster_iam_uptodate) next_cluster_ping = TIME + 1; // out-of-date slaves, do fast updates else next_cluster_ping = TIME + config->cluster_hb_interval; } - if (!config->cluster_iam_master) - continue; - // Run token bucket filtering queue.. // Only run it every 1/10th of a second. + // Runs on all machines both master and slave. { static clockt last_run = 0; if (last_run != TIME) { - tbf_run_timer(); last_run = TIME; - TIME = now(); - } - } - - // Handle timeouts, retries etc. - { - clockt last_clean = 0; - if (last_clean != TIME) - { - if (!last_clean) - last_clean = TIME - 10; - - regular_cleanups(TIME - last_clean); - last_clean = TIME; - TIME = now(); + tbf_run_timer(); } } - if (*config->accounting_dir) + /* Handle timeouts. Make sure that this gets run anyway, even if there was + * something to read, else under load this will never actually run.... + * + */ + if (config->cluster_iam_master && next_clean <= time_now) { - static clockt next_acct = 0; - static clockt next_shut_acct = 0; - - if (next_acct <= TIME) + if (regular_cleanups()) { - // Dump accounting data - next_acct = TIME + ACCT_TIME; - next_shut_acct = TIME + ACCT_SHUT_TIME; - dump_acct_info(1); + // Did it finish? + next_clean = time_now + 1 ; // Didn't finish. Check quickly. } - else if (next_shut_acct <= TIME) + else { - // Dump accounting data for shutdown sessions - next_shut_acct = TIME + ACCT_SHUT_TIME; - if (shut_acct_n) - dump_acct_info(0); + next_clean = time_now + config->cleanup_interval; // Did. Move to next interval. } } } @@ -3754,6 +3707,7 @@ static void update_config() } } memcpy(config->old_plugins, config->plugins, sizeof(config->plugins)); + if (!config->cleanup_interval) config->cleanup_interval = 10; if (!config->multi_read_count) config->multi_read_count = 10; if (!config->cluster_address) config->cluster_address = inet_addr(DEFAULT_MCAST_ADDR); if (!*config->cluster_interface)