From a350423d38f12d40b50a2d253ef2516d4409c2bc Mon Sep 17 00:00:00 2001 From: bodea Date: Mon, 30 May 2005 06:35:19 +0000 Subject: [PATCH] more changes to regular_cleanups(), process a slice of each of the tunnel, radius and session tables every tenth of a second --- Changes | 6 +- Docs/manual.html | 8 -- Docs/startup-config.5 | 8 +- l2tpns.c | 186 +++++++++++++++++++++++++++--------------- l2tpns.h | 4 +- radius.c | 5 +- 6 files changed, 125 insertions(+), 92 deletions(-) diff --git a/Changes b/Changes index 483ce87..dee7915 100644 --- a/Changes +++ b/Changes @@ -3,9 +3,9 @@ - Have slaves with BGP configured drop BGP on receipt of a shutdown signal, but hang about for an additional 5s to process any remaining traffic. -- Replace MAX_ACTIONS with a "cleanup_limit" config option, drop the - default for "cleanup_interval" to 2s (so as to process tunnel/RADIUS - retries more promptly). +- Run regular_cleanups every 1/10th second, looking at a sufficient + slice of each table to ensure that each entry is examined at least + once per second. * Mon May 23 2005 Brendan O'Dea 2.0.21 - Cluster changes from Michael, intended to prevent a stray master diff --git a/Docs/manual.html b/Docs/manual.html index 04f5b61..b37cba4 100644 --- a/Docs/manual.html +++ b/Docs/manual.html @@ -282,14 +282,6 @@ second. Even if this is disabled, you can see this information by running the uptime command on the CLI. -
  • cleanup_interval (int)
    -Interval between regular cleanups in seconds (default: 2). -
  • - -
  • cleanup_limit (int)
    -Maximum number of session actions to perform each cleanup (default: 50). -
  • -
  • multi_read_count (int)
    Number of packets to read off each of the UDP and TUN fds when returned as readable by select (default: 10). Avoids incurring the diff --git a/Docs/startup-config.5 b/Docs/startup-config.5 index d125433..8378fb7 100644 --- a/Docs/startup-config.5 +++ b/Docs/startup-config.5 @@ -2,7 +2,7 @@ .de Id .ds Dt \\$4 \\$5 .. -.Id $Id: startup-config.5,v 1.3.2.3 2005/05/30 02:55:42 bodea Exp $ +.Id $Id: startup-config.5,v 1.3.2.4 2005/05/30 06:35:19 bodea Exp $ .TH STARTUP-CONFIG 5 "\*(Dt" L2TPNS "File Formats and Conventions" .SH NAME startup\-config \- configuration file for l2tpns @@ -131,12 +131,6 @@ by running the uptime command on the CLI. .TP -.B cleanup_interval -Interval between regular cleanups in seconds (default: 2). -.TP -.B cleanup_limit -Maximum number of session actions to perform each cleanup (default: 50). -.TP .B multi_read_count Number of packets to read off each of the UDP and TUN fds when returned as readable by select (default: 10). Avoids incurring the diff --git a/l2tpns.c b/l2tpns.c index db73793..eb95d57 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.11 2005/05/30 02:55:41 bodea Exp $"; +char const *cvs_id_l2tpns = "$Id: l2tpns.c,v 1.73.2.12 2005/05/30 06:35:19 bodea Exp $"; #include #include @@ -112,8 +112,6 @@ 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("cleanup_limit", cleanup_limit, INT), CONFIG("multi_read_count", multi_read_count, INT), CONFIG("scheduler_fifo", scheduler_fifo, BOOL), CONFIG("lock_pages", lock_pages, BOOL), @@ -2063,37 +2061,64 @@ static void processtun(uint8_t * buf, int len) // Else discard. } -// Handle retries, timeouts -static int regular_cleanups(void) +// 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) { - 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; + // 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; + + int i; int a; - LOG(3, 0, 0, "Begin regular cleanup\n"); + // paranoia + if (period < 1) period = 1; - 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++) + // 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); + + for (i = 0; i < t_slice; i++) { + 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 @@ -2113,6 +2138,8 @@ static int regular_cleanups(void) tunnelsend(c->buf, c->length, t); c = c->next; } + + t_actions++; } } // Send hello @@ -2121,6 +2148,7 @@ static int regular_cleanups(void) 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 @@ -2131,13 +2159,28 @@ static int regular_cleanups(void) { 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++; + } } - count = 0; - for (i = 1; i <= config->cluster_highest_sessionid; i++) + for (i = 0; i < s_slice; i++) { s++; if (s > config->cluster_highest_sessionid) @@ -2151,13 +2194,14 @@ static int regular_cleanups(void) // 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"); - if (++count >= config->cleanup_limit) break; + s_actions++; continue; } @@ -2166,7 +2210,7 @@ static int regular_cleanups(void) { sessionshutdown(s, "No response to LCP ECHO requests"); STAT(session_timeout); - if (++count >= config->cleanup_limit) break; + s_actions++; continue; } @@ -2186,7 +2230,7 @@ static int regular_cleanups(void) 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 - if (++count >= config->cleanup_limit) break; + s_actions++; } // Check for actions requested from the CLI @@ -2200,6 +2244,7 @@ static int regular_cleanups(void) 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) @@ -2207,6 +2252,7 @@ static int regular_cleanups(void) 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) @@ -2217,6 +2263,7 @@ static int regular_cleanups(void) session[s].snoop_ip = cli_session_actions[s].snoop_ip; session[s].snoop_port = cli_session_actions[s].snoop_port; + s_actions++; send++; } @@ -2224,6 +2271,7 @@ static int regular_cleanups(void) { 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) @@ -2233,6 +2281,7 @@ static int regular_cleanups(void) cli_session_actions[s].throttle_out); throttle_session(s, cli_session_actions[s].throttle_in, cli_session_actions[s].throttle_out); + s_actions++; send++; } @@ -2240,6 +2289,7 @@ static int regular_cleanups(void) { 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) @@ -2249,39 +2299,17 @@ static int regular_cleanups(void) 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 >= config->cleanup_limit) break; } } - 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 >= config->cleanup_limit) - 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; + 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); } @@ -2376,7 +2404,6 @@ 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); @@ -2567,6 +2594,8 @@ static void mainloop(void) STAT(multi_read_exceeded); } + + TIME = now(); } // Runs on every machine (master and slaves). @@ -2582,37 +2611,60 @@ 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) { - last_run = TIME; tbf_run_timer(); + last_run = TIME; + TIME = now(); } } - /* 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) + // Handle timeouts, retries etc. { - if (regular_cleanups()) + clockt last_clean = 0; + if (last_clean != TIME) { - // Did it finish? - next_clean = time_now + 1 ; // Didn't finish. Check quickly. + if (!last_clean) + last_clean = TIME - 10; + + regular_cleanups(TIME - last_clean); + last_clean = TIME; + TIME = now(); } - else + } + + if (*config->accounting_dir) + { + static clockt next_acct = 0; + static clockt next_shut_acct = 0; + + 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) { - next_clean = time_now + config->cleanup_interval; // Did. Move to next interval. + // Dump accounting data for shutdown sessions + next_shut_acct = TIME + ACCT_SHUT_TIME; + if (shut_acct_n) + dump_acct_info(0); } } } @@ -3702,8 +3754,6 @@ static void update_config() } } memcpy(config->old_plugins, config->plugins, sizeof(config->plugins)); - if (!config->cleanup_interval) config->cleanup_interval = 2; - if (!config->cleanup_limit) config->cleanup_limit = 50; 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) diff --git a/l2tpns.h b/l2tpns.h index fcb896a..d97bd81 100644 --- a/l2tpns.h +++ b/l2tpns.h @@ -1,5 +1,5 @@ // L2TPNS Global Stuff -// $Id: l2tpns.h,v 1.49.2.14 2005/05/30 02:55:41 bodea Exp $ +// $Id: l2tpns.h,v 1.49.2.15 2005/05/30 06:35:19 bodea Exp $ #ifndef __L2TPNS_H__ #define __L2TPNS_H__ @@ -420,8 +420,6 @@ typedef struct char config_file[128]; int reload_config; // flag to re-read config (set by cli) - int cleanup_interval; // interval between regular cleanups (in seconds) - int cleanup_limit; // maximum number of actions to perform on sessions in each cleanup int multi_read_count; // amount of packets to read per fd in processing loop char tundevice[10]; // tun device name diff --git a/radius.c b/radius.c index 38b1f22..d6e3abb 100644 --- a/radius.c +++ b/radius.c @@ -1,6 +1,6 @@ // L2TPNS Radius Stuff -char const *cvs_id_radius = "$Id: radius.c,v 1.20.2.2 2005/05/03 05:10:52 bodea Exp $"; +char const *cvs_id_radius = "$Id: radius.c,v 1.20.2.3 2005/05/30 06:35:19 bodea Exp $"; #include #include @@ -142,7 +142,7 @@ void radiussend(uint16_t r, uint8_t state) if (radius[r].state != state) radius[r].try = 0; radius[r].state = state; - radius[r].retry = backoff(radius[r].try++); + radius[r].retry = backoff(radius[r].try++) + 20; // 3s, 4s, 6s, 10s... LOG(4, s, session[s].tunnel, "Send RADIUS id %d sock %d state %s try %d\n", r >> RADIUS_SHIFT, r & RADIUS_MASK, radius_state(radius[r].state), radius[r].try); @@ -691,7 +691,6 @@ void radiusretry(uint16_t r) if (s) t = session[s].tunnel; - radius[r].retry = backoff(radius[r].try + 1); switch (radius[r].state) { case RADIUSCHAP: // sending CHAP down PPP -- 2.20.1