From 004227046a683e59f3038bed5f77967131721bb1 Mon Sep 17 00:00:00 2001 From: Jon Sexson Date: Thu, 15 May 2014 12:42:45 +0300 Subject: [PATCH 2/4] Add per-client response window options Add support for "response_window" and "response_window_usec" in client sections - options overriding the home server response window for proxied requests, when set to non-zero. Clipped to the home server's "zombie_period". This allows faster home server failover when requests from higher-priority clients arrive. --- raddb/clients.conf | 12 ++++++++++++ src/include/radiusd.h | 1 + src/main/client.c | 19 +++++++++++++++++++ src/main/process.c | 39 ++++++++++++++++++++++++++++++--------- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/raddb/clients.conf b/raddb/clients.conf index 81f4501..878276d 100644 --- a/raddb/clients.conf +++ b/raddb/clients.conf @@ -174,6 +174,18 @@ client localhost { # virtual_server = home1 # + # If set to anything but zero, overrides the home server response + # window for proxied requests. Clipped to home server's + # "zombie_period". The default is zero. + # + # The time is specified with response_window and + # response_window_usec for second and microsecond parts + # respectively. + # + response_window = 0 + response_window_usec = 0 + + # # A pointer to the "home_server_pool" OR a "home_server" # section that contains the CoA configuration for this # client. For an example of a coa home server or pool, diff --git a/src/include/radiusd.h b/src/include/radiusd.h index 4aeff7d..ced55a6 100644 --- a/src/include/radiusd.h +++ b/src/include/radiusd.h @@ -82,6 +82,7 @@ typedef struct radclient { char *login; char *password; char *server; + struct timeval response_window; int number; /* internal use only */ CONF_SECTION const *cs; #ifdef WITH_STATS diff --git a/src/main/client.c b/src/main/client.c index feada49..ae8f1aa 100644 --- a/src/main/client.c +++ b/src/main/client.c @@ -490,6 +490,8 @@ RADCLIENT *client_find_old(fr_ipaddr_t const *ipaddr) static struct in_addr cl_ip4addr; static struct in6_addr cl_ip6addr; static char *cl_srcipaddr = NULL; +static int response_window = 0; +static int response_window_usec = 0; #ifdef WITH_TCP static char *hs_proto = NULL; #endif @@ -537,6 +539,10 @@ static const CONF_PARSER client_config[] = { offsetof(RADCLIENT, password), 0, NULL }, { "virtual_server", PW_TYPE_STRING_PTR, offsetof(RADCLIENT, server), 0, NULL }, + { "response_window", PW_TYPE_INTEGER, + 0, &response_window, "0" }, + { "response_window_usec", PW_TYPE_INTEGER, + 0, &response_window_usec, "0" }, #ifdef WITH_TCP { "proto", PW_TYPE_STRING_PTR, @@ -759,6 +765,19 @@ static RADCLIENT *client_parse(CONF_SECTION *cs, int in_server) break; } + FR_INTEGER_BOUND_CHECK("response_window", response_window, >=, 0); + FR_INTEGER_BOUND_CHECK("response_window", response_window, <=, 60); + FR_INTEGER_BOUND_CHECK("response_window", response_window, <=, main_config.max_request_time); + FR_INTEGER_BOUND_CHECK("response_window_usec", response_window_usec, >=, 0); + FR_INTEGER_BOUND_CHECK("response_window_usec", response_window_usec, <=, 999999); + FR_INTEGER_COND_CHECK("response_window_usec", response_window_usec, + response_window < 60 && + response_window < main_config.max_request_time, + 0); + + c->response_window.tv_sec = response_window; + c->response_window.tv_usec = response_window_usec; + #ifdef WITH_DYNAMIC_CLIENTS if (c->client_server) { c->secret = talloc_typed_strdup(c, "testing123"); diff --git a/src/main/process.c b/src/main/process.c index e6deafd..91818a9 100644 --- a/src/main/process.c +++ b/src/main/process.c @@ -284,6 +284,7 @@ void radius_update_listener(rad_listen_t *this) static int request_num_counter = 0; #ifdef WITH_PROXY +static void request_response_window(REQUEST *request, struct timeval *response_window); static int request_will_proxy(REQUEST *request); static int request_proxy(REQUEST *request, int retransmit); STATE_MACHINE_DECL(proxy_wait_for_reply); @@ -419,7 +420,7 @@ static void request_timer(void *ctx) */ STATE_MACHINE_DECL(request_done) { - struct timeval now, when; + struct timeval now, response_window, when; #ifdef WITH_PROXY char buffer[128]; #endif @@ -595,7 +596,8 @@ STATE_MACHINE_DECL(request_done) when.tv_sec += request->home_server->coa_mrd; } else #endif - timeradd(&when, &request->home_server->response_window, &when); + request_response_window(request, &response_window); + timeradd(&when, &response_window, &when); /* * We haven't received all responses, AND there's still @@ -1913,6 +1915,24 @@ static int eol_listener(void *ctx, void *data) ***********************************************************************/ /* + * Determine request response window. + */ +static void request_response_window(REQUEST *request, struct timeval *response_window) +{ + if (timerisset(&request->client->response_window)) { + if (request->client->response_window.tv_sec >= + request->home_server->zombie_period) { + response_window->tv_sec = request->home_server->zombie_period; + response_window->tv_usec = 0; + } else { + *response_window = request->client->response_window; + } + } else { + *response_window = request->home_server->response_window; + } +} + +/* * Called with the proxy mutex held */ static void remove_from_proxy_hash_nl(REQUEST *request, bool yank) @@ -3031,7 +3051,8 @@ static void home_trigger(home_server_t *home, char const *trigger) exec_trigger(&my_request, home->cs, trigger, false); } -static void mark_home_server_zombie(home_server_t *home, struct timeval *now) +static void mark_home_server_zombie(home_server_t *home, + struct timeval *now, struct timeval *response_window) { time_t start; char buffer[128]; @@ -3081,7 +3102,7 @@ static void mark_home_server_zombie(home_server_t *home, struct timeval *now) PROXY( "Marking home server %s port %d as zombie (it has not responded in %d.%.6d seconds).", inet_ntop(home->ipaddr.af, &home->ipaddr.ipaddr, buffer, sizeof(buffer)), - home->port, (int)home->response_window.tv_sec, (int)home->response_window.tv_usec); + home->port, (int)response_window->tv_sec, (int)response_window->tv_usec); ping_home_server(home); } @@ -3161,7 +3182,7 @@ void mark_home_server_dead(home_server_t *home, struct timeval *when) STATE_MACHINE_DECL(proxy_wait_for_reply) { - struct timeval now, when; + struct timeval now, response_window, when; home_server_t *home = request->home_server; char buffer[128]; @@ -3256,6 +3277,7 @@ STATE_MACHINE_DECL(proxy_wait_for_reply) break; case FR_ACTION_TIMER: + request_response_window(request, &response_window); #ifdef WITH_TCP if (!request->proxy_listener || (request->proxy_listener->status != RAD_LISTEN_STATUS_KNOWN)) { @@ -3280,7 +3302,7 @@ STATE_MACHINE_DECL(proxy_wait_for_reply) * zombie if it doesn't respond to us. It may be * responding to other (better looking) packets. */ - timeradd(&request->proxy->timestamp, &home->response_window, &when); + timeradd(&request->proxy->timestamp, &response_window, &when); /* * Not at the response window. Set the timer for @@ -3288,8 +3310,7 @@ STATE_MACHINE_DECL(proxy_wait_for_reply) */ if (timercmp(&when, &now, >)) { RDEBUG("Expecting proxy response no later than %d.%.6d seconds from now", - (int)home->response_window.tv_sec, - (int)home->response_window.tv_usec); + (int)response_window.tv_sec, (int)response_window.tv_usec); STATE_MACHINE_TIMER(FR_ACTION_TIMER); return; } @@ -3315,7 +3336,7 @@ STATE_MACHINE_DECL(proxy_wait_for_reply) && (home->proto != IPPROTO_TCP) #endif ) { - mark_home_server_zombie(home, &now); + mark_home_server_zombie(home, &now, &response_window); } FR_STATS_TYPE_INC(home->stats.total_timeouts); -- 1.9.2