A Suggestion for rlm_ldap.

Alister Winfield alister at ticklers.org
Thu Mar 24 10:30:06 CET 2011


A problem we have had and will continue to have without a small change to rlm_ldap's connection handling is that it defeats the ability of a load balancer to do its job. The issue being that if there is a temporary problem or maintenance on a bunch of LDAP servers all the active connections can end up on a tiny proportion of the servers. 

I understand that doing 1 query per connection would be terrible for performance so how about have 'max-requests-per-connection' in the code and drop the current connection after doing that many searches. Roughly (and untested) something like this. 


dogmatix:rlm_ldap alister$ git diff
diff --git a/src/modules/rlm_ldap/rlm_ldap.c b/src/modules/rlm_ldap/rlm_ldap.c
index 450279b..5eb1834 100644
--- a/src/modules/rlm_ldap/rlm_ldap.c
+++ b/src/modules/rlm_ldap/rlm_ldap.c
@@ -78,6 +78,10 @@ RCSID("$Id$")
 #define MAX_FAILED_CONNS_RESTART       4
 #define MAX_FAILED_CONNS_START         5
 
+/* When connecting to a server farm its a good idea to reconnect regularly 
+ * to allow a load balancer to do its job correctly.*/
+#define MAX_REQUESTS_PER_CONNECTION    2000
+
 #ifdef NOVELL_UNIVERSAL_PASSWORD
 
 /* Universal Password Length */
@@ -116,6 +120,7 @@ typedef struct ldap_conn {
        char            bound;
        char            locked;
        int             failed_conns;
+       int             query_count;
 #ifdef HAVE_PTHREAD_H
        pthread_mutex_t mutex;
 #endif
@@ -856,12 +861,21 @@ retry:
                }
                conn->bound = 1;
                conn->failed_conns = 0;
+               conn->query_count = 0;
+       }
+       /* If we have performed greater than a fixed number of queries on this connection force a reconnect */
+       if (conn->query_count > MAX_REQUESTS_PER_CONNECTION) {
+               conn->bound=0;
+               conn->query_count=0;
+               goto retry;
        }
 
        tv.tv_sec = inst->timeout;
        tv.tv_usec = 0;
        DEBUG2("  [%s] performing search in %s, with filter %s", inst->xlat_name, 
               search_basedn ? search_basedn : "(null)" , filter);
+
+       conn->query_count++;
        switch (ldap_search_st(conn->ld, search_basedn, scope, filter,
                               attrs, 0, &tv, result)) {
        case LDAP_SUCCESS:
@@ -1939,7 +1953,6 @@ static int ldap_authenticate(void *instance, REQUEST * request)
                                        if (conn1->failed_conns >= MAX_FAILED_CONNS_END){
                                                conn1->failed_conns = MAX_FAILED_CONNS_RESTART;
                                                conn1->bound = 0;
-                                       }
                                }
 retry:
                                if (!conn1->bound || conn1->ld == NULL) {
@@ -1955,6 +1968,7 @@ retry:
                                        }
                                        conn1->bound = 1;
                                        conn1->failed_conns = 0;
+                                       conn1->query_count = 0;
                                }
                                RDEBUG("Performing NMAS Authentication for user: %s, seq: %s \n", user_dn,seq);





More information about the Freeradius-Devel mailing list