]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip: Add global option to limit the maximum time for initial qualifies 48/48/8
authorGeorge Joseph <george.joseph@fairview5.com>
Sat, 11 Apr 2015 22:04:32 +0000 (16:04 -0600)
committerGeorge Joseph <george.joseph@fairview5.com>
Thu, 16 Apr 2015 21:44:45 +0000 (16:44 -0500)
Currently when Asterisk starts initial qualifies of contacts are spread out
randomly between 0 and qualify_timeout to prevent network and system overload.
If a contact's qualify_frequency is 5 minutes however, that contact may be
unavailable to accept calls for the entire 5 minutes after startup.  So while
staggering the initial qualifies is a good idea, basing the time on
qualify_timeout could leave contacts unavailable for too long.

This patch adds a new global parameter "max_initial_qualify_time" that sets the
maximum time for the initial qualifies.  This way you could make sure that all
your contacts are initialy, randomly qualified within say 30 seconds but still
have the contact's ongoing qualifies at a 5 minute interval.

If max_initial_qualify_time is > 0, the formula is initial_interval =
min(max_initial_interval, qualify_timeout * random().  If not set,
qualify_timeout is used.

The default is "0" (disabled).

ASTERISK-24863 #close

Change-Id: Ib80498aa1ea9923277bef51d6a9015c9c79740f4
Tested-by: George Joseph <george.joseph@fairview5.com>
CHANGES
configs/samples/pjsip.conf.sample
contrib/ast-db-manage/config/versions/a541e0b5e89_add_pjsip_max_initial_qualify_time.py [new file with mode: 0644]
include/asterisk/res_pjsip.h
res/res_pjsip.c
res/res_pjsip/config_global.c
res/res_pjsip/pjsip_options.c

diff --git a/CHANGES b/CHANGES
index 7e54a2095660b89531c1e548b7d559eac2697d1e..ef78d97bf292ddf3aa137d8b4fca2d14499d42cd 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -147,6 +147,10 @@ res_pjsip
    unavailable.  When any contact becomes available, the endpoint will status
    will change back to "Reachable".
 
+ * A new global option has been added: "max_initial_qualify_time", which
+   sets the maximum amount of time from startup that qualifies should be
+   attempted on all contacts.
+
 res_ari_channels
 ------------------
  * Two new events, 'ChannelHold' and 'ChannelUnhold', have been added to the
index 57b712a873a983306f86a4051a9646e92e92ed94..0f95d19e0065ed36123367508fb236a36708925d 100644 (file)
             ; The order by which endpoint identifiers are given priority.
             ; Identifier names are derived from res_pjsip_endpoint_identifier_*
             ; modules. (default: ip,username,anonymous)
-
+;max_initial_qualify_time=4 ; The maximum amount of time (in seconds) from
+                              startup that qualifies should be attempted on all
+                              contacts.  If greater than the qualify_frequency
+                              for an aor, qualify_frequency will be used instead.
 
 ; MODULE PROVIDING BELOW SECTION(S): res_pjsip_acl
 ;==========================ACL SECTION OPTIONS=========================
diff --git a/contrib/ast-db-manage/config/versions/a541e0b5e89_add_pjsip_max_initial_qualify_time.py b/contrib/ast-db-manage/config/versions/a541e0b5e89_add_pjsip_max_initial_qualify_time.py
new file mode 100644 (file)
index 0000000..0ffd784
--- /dev/null
@@ -0,0 +1,20 @@
+"""add pjsip max_initial_qualify_time
+
+Revision ID: a541e0b5e89
+Revises: 461d7d691209
+Create Date: 2015-04-15 14:37:36.424471
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = 'a541e0b5e89'
+down_revision = '461d7d691209'
+
+from alembic import op
+import sqlalchemy as sa
+
+def upgrade():
+    op.add_column('ps_globals', sa.Column('max_initial_qualify_time', sa.Integer))
+
+def downgrade():
+    op.drop_column('ps_globals', 'max_initial_qualify_time')
index 184cb57451ba09ad4e2501f31307d078f35f5a8a..99b65ab088b2810e12ceeae84db728f9467d3112 100644 (file)
@@ -1995,4 +1995,12 @@ char *ast_sip_get_endpoint_identifier_order(void);
  */
 unsigned int ast_sip_get_keep_alive_interval(void);
 
+/*!
+ * \brief Retrieve the system max initial qualify time.
+ *
+ * \retval the maximum initial qualify time.
+ */
+unsigned int ast_sip_get_max_initial_qualify_time(void);
+
+
 #endif /* _RES_PJSIP_H */
index 4f77b51021575bf998144beac1c78a84727147d5..e54f2c7cce52e27bee815d13771f2055e72cb014 100644 (file)
                                <configOption name="keep_alive_interval" default="0">
                                        <synopsis>The interval (in seconds) to send keepalives to active connection-oriented transports.</synopsis>
                                </configOption>
+                               <configOption name="max_initial_qualify_time" default="0">
+                                       <synopsis>The maximum amount of time from startup that qualifies should be attempted on all contacts.
+                                       If greater than the qualify_frequency for an aor, qualify_frequency will be used instead.</synopsis>
+                               </configOption>
                                <configOption name="type">
                                        <synopsis>Must be of type 'global'.</synopsis>
                                </configOption>
index 2aa15838f4e8f12b30676bee43d79db686dfe2a2..42ba23487c6e038905eea285c70529f8a05b25a3 100644 (file)
@@ -33,6 +33,7 @@
 #define DEFAULT_OUTBOUND_ENDPOINT "default_outbound_endpoint"
 #define DEFAULT_DEBUG "no"
 #define DEFAULT_ENDPOINT_IDENTIFIER_ORDER "ip,username,anonymous"
+#define DEFAULT_MAX_INITIAL_QUALIFY_TIME 0
 
 static char default_useragent[256];
 
@@ -50,6 +51,8 @@ struct global_config {
        unsigned int max_forwards;
        /* The interval at which to send keep alive messages to active connection-oriented transports */
        unsigned int keep_alive_interval;
+       /* The maximum time for all contacts to be qualified at startup */
+       unsigned int max_initial_qualify_time;
 };
 
 static void global_destructor(void *obj)
@@ -161,6 +164,21 @@ unsigned int ast_sip_get_keep_alive_interval(void)
        return interval;
 }
 
+unsigned int ast_sip_get_max_initial_qualify_time(void)
+{
+       unsigned int time;
+       struct global_config *cfg;
+
+       cfg = get_global_cfg();
+       if (!cfg) {
+               return DEFAULT_MAX_INITIAL_QUALIFY_TIME;
+       }
+
+       time = cfg->max_initial_qualify_time;
+       ao2_ref(cfg, -1);
+       return time;
+}
+
 /*!
  * \internal
  * \brief Observer to set default global object if none exist.
@@ -271,6 +289,9 @@ int ast_sip_initialize_sorcery_global(void)
        ast_sorcery_object_field_register(sorcery, "global", "keep_alive_interval",
                __stringify(DEFAULT_KEEPALIVE_INTERVAL),
                OPT_UINT_T, 0, FLDSET(struct global_config, keep_alive_interval));
+       ast_sorcery_object_field_register(sorcery, "global", "max_initial_qualify_time",
+               __stringify(DEFAULT_MAX_INITIAL_QUALIFY_TIME),
+               OPT_UINT_T, 0, FLDSET(struct global_config, max_initial_qualify_time));
 
        if (ast_sorcery_instance_observer_add(sorcery, &observer_callbacks_global)) {
                return -1;
index dc5a70175bd05a2ef7c16736ba8fbdc6307cd002..9c0a1379d0905987fdac38c8c294a750bd44a4c1 100644 (file)
@@ -994,14 +994,20 @@ static int qualify_and_schedule_cb(void *obj, void *arg, int flags)
        struct ast_sip_contact *contact = obj;
        struct ast_sip_aor *aor = arg;
        int initial_interval;
+       int max_time = ast_sip_get_max_initial_qualify_time();
 
        contact->qualify_frequency = aor->qualify_frequency;
        contact->qualify_timeout = aor->qualify_timeout;
        contact->authenticate_qualify = aor->authenticate_qualify;
 
        /* Delay initial qualification by a random fraction of the specified interval */
-       initial_interval = contact->qualify_frequency * 1000;
-       initial_interval = (int)(initial_interval * ast_random_double());
+       if (max_time && max_time < contact->qualify_frequency) {
+               initial_interval = max_time;
+       } else {
+               initial_interval = contact->qualify_frequency;
+       }
+
+       initial_interval = (int)((initial_interval * 1000) * ast_random_double());
 
        if (contact->qualify_frequency) {
                schedule_qualify(contact, initial_interval);