res_pjsip_outbound_registration: Make max random delay configurable.

Currently, PJSIP will randomly wait up to 10 seconds for each
outbound registration's initial attempt. The reason for this
is to avoid having all outbound registrations attempt to register
simultaneously.

This can create limitations with the test suite where we need to
be able to receive inbound calls potentially within 10 seconds of
starting up. For instance, we might register to another server
and then try to receive a call through the registration, but if
the registration hasn't happened yet, this will fail, and hence
this inconsistent behavior can cause tests to fail. Ultimately,
this requires a smaller random value because there may be no good
reason to wait for up to 10 seconds in these circumstances.

To address this, a new config option is introduced which makes this
maximum delay configurable. This allows, for instance, this to be
set to a very small value in test systems to ensure that registrations
happen immediately without an unnecessary delay, and can be used more
generally to control how "tight" the initial outbound registrations
are.

ASTERISK-29965 #close

Change-Id: Iab989a8e94323e645f3a21cbb6082287c7b2f3fd
16.27
Naveen Albert 3 years ago committed by Joshua Colp
parent 0350a05aea
commit c1611e7d1b

@ -1297,6 +1297,11 @@
; (default: "")
;outbound_proxy= ; Proxy through which to send registrations, a full SIP URI
; must be provided (default: "")
;max_random_initial_delay=10 ; Maximum random delay for initial registrations (default: 10)
; Generally it is a good idea to space out registrations
; to not overload the system. If you have a small number
; of registrations and need them to register more quickly,
; you can reduce this to a lower value.
;retry_interval=60 ; Interval in seconds between retries if outbound
; registration is unsuccessful (default: "60")
;forbidden_retry_interval=0 ; Interval used when receiving a 403 Forbidden

@ -0,0 +1,21 @@
"""max_random_initial_delay
Revision ID: 18e0805d367f
Revises: 0bee61aa9425
Create Date: 2022-05-18 17:07:02.626045
"""
# revision identifiers, used by Alembic.
revision = '18e0805d367f'
down_revision = '0bee61aa9425'
from alembic import op
import sqlalchemy as sa
def upgrade():
op.add_column('ps_registrations', sa.Column('max_random_initial_delay', sa.Integer))
def downgrade():
op.drop_column('ps_registrations', 'max_random_initial_delay')

@ -104,6 +104,15 @@
<configOption name="outbound_proxy" default="">
<synopsis>Full SIP URI of the outbound proxy used to send registrations</synopsis>
</configOption>
<configOption name="max_random_initial_delay" default="10">
<synopsis>Maximum interval in seconds for which an initial registration may be randomly delayed</synopsis>
<description>
<para>By default, registrations are randomly delayed by a small amount to prevent
too many registrations from being made simultaneously.</para>
<para>Depending on your system usage, it may be desirable to set this to a smaller
or larger value to have fine grained control over the size of this random delay.</para>
</description>
</configOption>
<configOption name="retry_interval" default="60">
<synopsis>Interval in seconds between retries if outbound registration is unsuccessful</synopsis>
</configOption>
@ -305,6 +314,8 @@ struct sip_outbound_registration {
);
/*! \brief Requested expiration time */
unsigned int expiration;
/*! \brief Maximum random initial delay interval for initial registrations */
unsigned int max_random_initial_delay;
/*! \brief Interval at which retries should occur for temporal responses */
unsigned int retry_interval;
/*! \brief Interval at which retries should occur for permanent responses */
@ -1464,6 +1475,7 @@ static int sip_outbound_registration_perform(void *data)
struct sip_outbound_registration_state *state = data;
struct sip_outbound_registration *registration = ao2_bump(state->registration);
size_t i;
int max_delay;
/* Just in case the client state is being reused for this registration, free the auth information */
ast_sip_auth_vector_destroy(&state->client_state->outbound_auths);
@ -1483,10 +1495,12 @@ static int sip_outbound_registration_perform(void *data)
state->client_state->retries = 0;
state->client_state->support_path = registration->support_path;
state->client_state->auth_rejection_permanent = registration->auth_rejection_permanent;
max_delay = registration->max_random_initial_delay;
pjsip_regc_update_expires(state->client_state->client, registration->expiration);
schedule_registration(state->client_state, (ast_random() % 10) + 1);
/* n mod 0 is undefined, so don't let that happen */
schedule_registration(state->client_state, (max_delay ? ast_random() % max_delay : 0) + 1);
ao2_ref(registration, -1);
ao2_ref(state, -1);
@ -2296,6 +2310,7 @@ static int load_module(void)
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "transport", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, transport));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_random_initial_delay", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_random_initial_delay));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "forbidden_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, forbidden_retry_interval));
ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "fatal_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, fatal_retry_interval));

Loading…
Cancel
Save