Allow requests to fail over to live servers earlier
authorAlan T. DeKok <aland@freeradius.org>
Fri, 17 Jul 2009 12:33:23 +0000 (14:33 +0200)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 17 Jul 2009 12:33:23 +0000 (14:33 +0200)
raddb/proxy.conf
src/include/realms.h
src/main/event.c
src/main/realms.c

index 4f49b7a..5655dbb 100644 (file)
@@ -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
index 3baf2b3..34d22a6 100644 (file)
@@ -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;
index e3e946a..7c140bd 100644 (file)
@@ -1082,18 +1082,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
index 5db714e..4d1be77 100644 (file)
@@ -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,
@@ -1783,6 +1785,7 @@ home_server *home_server_ldb(const char *realmname,
        int             start;
        int             count;
        home_server     *found = NULL;
+       home_server     *zombie = NULL;
        VALUE_PAIR      *vp;
 
        /*
@@ -1867,6 +1870,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) {
@@ -1945,6 +1957,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) {