]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add support for timeout on sqlippool allocate_clear 2429/head
authorMaximumG <maxime.gerges@live.fr>
Mon, 28 Jan 2019 07:46:45 +0000 (08:46 +0100)
committerMaxime Gerges <maxime.gerges@ariane.network>
Tue, 29 Jan 2019 08:54:08 +0000 (09:54 +0100)
Add allocate_clear_timeout support to sqlippol

raddb/mods-available/sqlippool
src/modules/rlm_sqlippool/rlm_sqlippool.c

index 40356b637d9ec0bf5847b59b62c49b76252a578f..a628fbedd87ee5184e4c01a03fbebc548e49c661 100644 (file)
@@ -27,6 +27,12 @@ sqlippool {
        # IP lease duration. (Leases expire even if Acct Stop packet is lost)
        lease_duration = 3600
 
+       #
+       # Timeout between each consecutive 'allocate_clear' queries (default: 1s)
+       # This will avoid having too many deadlock issues, especially on MySQL backend.
+       #
+       allocate_clear_timeout = 1
+
        #
        #  As of 3.0.16, the 'ipv6 = yes' configuration is deprecated.
        #  You should use the "attribute_name" configuration item
index 3eb4f12a95d7c844104c85f72a8a5072a3150258..e43ea0af41ad675075072a2ba8cca27c6fd9edcc 100644 (file)
@@ -55,6 +55,7 @@ typedef struct rlm_sqlippool_t {
        time_t          last_clear;             //!< So we only do it once a second.
        char const      *allocate_begin;        //!< SQL query to begin.
        char const      *allocate_clear;        //!< SQL query to clear an IP.
+       uint32_t    allocate_clear_timeout; //!< Number of second between two allocate_clear SQL query
        char const      *allocate_find;         //!< SQL query to find an unused IP.
        char const      *allocate_update;       //!< SQL query to mark an IP as used.
        char const      *allocate_commit;       //!< SQL query to commit.
@@ -140,6 +141,9 @@ static CONF_PARSER module_config[] = {
        { "allocate-clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_clear), NULL },
        { "allocate_clear", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT , rlm_sqlippool_t, allocate_clear), ""  },
 
+       { "allocate-clear-timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_clear_timeout), NULL },
+       { "allocate_clear_timeout", FR_CONF_OFFSET(PW_TYPE_INTEGER, rlm_sqlippool_t, allocate_clear_timeout), "1" },
+
        { "allocate-find", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_DEPRECATED, rlm_sqlippool_t, allocate_find), NULL },
        { "allocate_find", FR_CONF_OFFSET(PW_TYPE_STRING | PW_TYPE_XLAT | PW_TYPE_REQUIRED, rlm_sqlippool_t, allocate_find), ""  },
 
@@ -523,6 +527,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_post_auth(void *instance, REQUEST *reque
        VALUE_PAIR *vp;
        rlm_sql_handle_t *handle;
        time_t now;
+       uint32_t diff_time;
 
        /*
         *      If there is already an attribute in the reply do nothing
@@ -554,10 +559,13 @@ static rlm_rcode_t CC_HINT(nonnull) mod_post_auth(void *instance, REQUEST *reque
         *      race conditions for the check, but so what.  The
         *      actual work is protected by a transaction.  The idea
         *      here is that if we're allocating 100 IPs a second,
-        *      we're only do 1 CLEAR per second.
+        *      we're only do 1 CLEAR per allocate_clear_timeout.
+        *  This will avoid having several queries to deadlock and blocking all
+        *  the sqlippool module.
         */
        now = time(NULL);
-       if (inst->allocate_clear && *inst->allocate_clear && (inst->last_clear < now)) {
+       diff_time = difftime(now, inst->last_clear);
+       if (inst->allocate_clear && *inst->allocate_clear && diff_time >= inst->allocate_clear_timeout) {
                inst->last_clear = now;
 
                DO_PART(allocate_begin);