From d5e5d7c11d45e9eb663d0cad60cd49548c8a5f5d Mon Sep 17 00:00:00 2001 From: "Alan T. DeKok" Date: Fri, 17 Jul 2009 14:33:23 +0200 Subject: [PATCH] Allow requests to fail over to live servers earlier --- raddb/proxy.conf | 38 +++++++++++++++++++++++++++++--------- src/include/realms.h | 1 + src/main/event.c | 24 ++++++++++++++++-------- src/main/realms.c | 21 +++++++++++++++++++++ 4 files changed, 67 insertions(+), 17 deletions(-) diff --git a/raddb/proxy.conf b/raddb/proxy.conf index 4f49b7a..5655dbb 100644 --- a/raddb/proxy.conf +++ b/raddb/proxy.conf @@ -218,21 +218,41 @@ home_server localhost { require_message_authenticator = no # - # If the home server doesn't respond to the request within - # this time, this server will consider the request dead, and - # respond to the NAS with an Access-Reject. + # If the home server does not respond to a request within + # this time, this server will initiate "zombie_period". # - # If NO responses are received to any requests sent within this - # time period, the home server will be marked "zombie", as below. + # The response window is large because responses MAY be slow, + # especially when proxying across the Internet. # # Useful range of values: 5 to 60 response_window = 20 # - # If the home server does not respond to ANY packets for - # a certain time, consider it dead. This time period is - # called the "zombie" period, because the server is neither - # alive nor dead. + # If you want the old behavior of the server rejecting + # proxied requests after "response_window" timeout, set + # the following configuration item to "yes". + # + # This configuration WILL be removed in a future release + # If you believe you need it, email the freeradius-users + # list, and explain why it should stay in the server. + # +# no_response_fail = no + + # + # If the home server does not respond to ANY packets during + # the "zombie period", it will be considered to be dead. + # + # A home server that is marked "zombie" will be used for + # proxying as a low priority. If there are live servers, + # they will always be preferred to a zombie. Requests will + # be proxied to a zombie server ONLY when there are no + # live servers. + # + # Any request that is proxied to a home server will continue + # to be sent to that home server until the home server is + # marked dead. At that point, it will fail over to another + # server, if a live server is available. If none is available, + # then the "post-proxy-type fail" handler will be called. # # If "status_check" below is something other than "none", then # the server will start sending status checks at the start of diff --git a/src/include/realms.h b/src/include/realms.h index 923e825..92c891b 100644 --- a/src/include/realms.h +++ b/src/include/realms.h @@ -48,6 +48,7 @@ typedef struct home_server { struct timeval when; int response_window; + int no_response_fail; int max_outstanding; /* don't overload it */ int currently_outstanding; int message_authenticator; diff --git a/src/main/event.c b/src/main/event.c index 2f8ae2c..dc8981b 100644 --- a/src/main/event.c +++ b/src/main/event.c @@ -1077,18 +1077,26 @@ static void no_response_to_proxied_request(void *ctx) return; } - radlog(L_ERR, "Rejecting request %d due to lack of any response from home server %s port %d", - request->number, - inet_ntop(request->proxy->dst_ipaddr.af, - &request->proxy->dst_ipaddr.ipaddr, - buffer, sizeof(buffer)), - request->proxy->dst_port); - check_for_zombie_home_server(request); home = request->home_server; - post_proxy_fail_handler(request); + /* + * The default as of 2.1.7 is to allow requests to + * fail-over to a backup home server when this one does + * not respond. The old behavior can be configured as + * well. + */ + if (home->no_response_fail) { + radlog(L_ERR, "Rejecting request %d due to lack of any response from home server %s port %d", + request->number, + inet_ntop(request->proxy->dst_ipaddr.af, + &request->proxy->dst_ipaddr.ipaddr, + buffer, sizeof(buffer)), + request->proxy->dst_port); + + post_proxy_fail_handler(request); + } /* * Don't touch request due to race conditions diff --git a/src/main/realms.c b/src/main/realms.c index 72065e1..3d028a0 100644 --- a/src/main/realms.c +++ b/src/main/realms.c @@ -303,6 +303,8 @@ static CONF_PARSER home_server_config[] = { { "response_window", PW_TYPE_INTEGER, offsetof(home_server,response_window), NULL, "30" }, + { "no_response_fail", PW_TYPE_BOOLEAN, + offsetof(home_server,no_response_fail), NULL, NULL }, { "max_outstanding", PW_TYPE_INTEGER, offsetof(home_server,max_outstanding), NULL, "65536" }, { "require_message_authenticator", PW_TYPE_BOOLEAN, @@ -1823,6 +1825,7 @@ home_server *home_server_ldb(const char *realmname, int start; int count; home_server *found = NULL; + home_server *zombie = NULL; VALUE_PAIR *vp; /* @@ -1907,6 +1910,15 @@ home_server *home_server_ldb(const char *realmname, if (!home) continue; /* + * Remember zombies, but skip them. If there are + * no live servers, then we will use a zombie one. + */ + if (home->state == HOME_STATE_ZOMBIE) { + zombie = home; + continue; + } + + /* * Skip zombie && dead home servers. */ if (home->state != HOME_STATE_ALIVE) { @@ -1985,6 +1997,15 @@ home_server *home_server_ldb(const char *realmname, } /* loop over the home servers */ /* + * We have no live servers, BUT we have a zombie. Use + * the zombie as a last resort. + */ + if (!found && zombie) { + found = zombie; + zombie = NULL; + } + + /* * There's a fallback if they're all dead. */ if (!found && pool->fallback) { -- 2.1.4