QUALITY-BASED ROUTING module
Admin Guide
Section titled “Admin Guide”Overview
Section titled “Overview”qrouting is a module which sits on top of drouting, dialog and tm and performs live tracking of a series of essential gateway signaling quality indicators (i.e. ASR, CCR, PDD, AST, ACD — more details below). Thus, qrouting is able to adjust the prefix routing behavior at runtime, by dynamically re-ordering the gateways based on how well they perform during live traffic, such that:
- well-performing gateways get prioritized for routing
- gateways which show a degradation in signaling quality are demoted to the end of the routing list
Monitored Statistics
Section titled “Monitored Statistics”The module keeps track of a series of statistics, for each drouting (prefix, destination) pair, where a “destination” may be either a gateway or a carrier. The statistics are:
- ASR (Answer Seizure Ratio) - the percentage of telephone calls which are answered (200 reply status code).
- CCR (Call Completion Ratio) - the percentage of telephone calls which are answered back by the gateway, excluding 5xx, 6xx reply codes and internal 408 timeouts. The following is always true: CCR >= ASR.
- PDD (Post Dial Delay) - the duration, in milliseconds, between the receival of the initial INVITE and the receival of the first 180/183 provisional reply (the call state advances to “ringing”).
- AST (Average Setup Time) - the duration, in milliseconds, between the receival of the initial INVITE and the receival of the first 200 OK reply (the call state advances to “answered”). The following is always true: AST >= PDD.
- ACD (Average Call Duration) - the duration, in seconds, between the receival of the initial INVITE and the receival of the first BYE request from either participant (the call state advances to “ended”).
Dependencies
Section titled “Dependencies”OpenSIPS Modules
Section titled “OpenSIPS Modules”The following modules must be loaded for this module to work:
- an SQL DB module, offering access to the “qr_profiles” table
- tm
- dialog
- drouting
Exported Parameters
Section titled “Exported Parameters”db_url (string)
Section titled “db_url (string)”An SQL database URL.
Default value is NULL.
modparam("qrouting", "db_url", "mysql://opensips:opensipsrw@localhost/opensips")table_name (string)
Section titled “table_name (string)”The name of the quality-based routing profiles table.
Default value is “qr_profiles”.
modparam("qrouting", "table_name", "qr_profiles_bak")algorithm (integer)
Section titled “algorithm (integer)”Quality-based destination selection/balancing algorithm to use.
Possible values:
- “dynamic-weights” - for each prefix, all destinations start with equal weights and receive an equal share of the traffic. As signaling statistics are gathered for the destinations, the ones which underperform will receive less traffic, based on the “penalty” columns of the qr_profiles table
- “best-dest-first” - for each prefix, the 1st (i.e. best scoring) destination will receive all the traffic as long as its quality stays the same. Initially, all destinations start with a perfect score. This score may degrade if one or more signaling statistics fall below the “warn” or “crit” thresholds during routing, case in which the destinations will be sorted accordingly and traffic will be routed to the newly determined 1st position in the list NOTE: for optimal results when using the “best-dest-first” algorithm, the destinations must be provisioned in descending order of their expected quality! (i.e. best quality gateways must be placed towards the start of the list)
Default value is “dynamic-weights”.
modparam("qrouting", "algorithm", "best-dest-first")history_span (integer)
Section titled “history_span (integer)”The duration (in minutes) that a gateway’s statistics for a given call will be kept for.
Default value is 30 minutes.
modparam("qrouting", "history_span", 15)sampling_interval (integer)
Section titled “sampling_interval (integer)”The duration (in seconds) of the statistics sampling window. Every sampling interval seconds, the accumulated statistics during the most recent sampling window get added to each gateway, while the oldest sampled interval statistics are subtracted (rotated away) from each gateway.
A lower value will lead to a closer to realtime adjustment to traffic changes, but it will also increase CPU usage and internal contention due to locking.
Default value is 5 seconds.
modparam("qrouting", "sampling_interval", 5)extra_stats (string)
Section titled “extra_stats (string)”A semicolon-separated list of custom statistics to be additionally kept and monitored by the module. In order to gather these statistics, the module expects the script writer to call qr set xstat whenever they want to increment a custom statistic for a (prefix, destination) tuple.
Extra statistics come in two flavours: positive (a higher value is better, e.g. ASR) or negative (a lower value is better, e.g. PDD). The flavour determines the comparison operator to be used against the statistics’s thresholds, and can be specified by prepending ”+” or ”-”, respectively, in front of the statistic’s name (see example below).
The minimally accepted number of samples for each statistic may be changed using the optional /<min_samples> suffix. Default value: 30 samples (minimum).
The thresholds and penalties for a custom statistic must be provided via the qr_profiles table, by extending it with 4 columns for each extra statistic, named according to these templates:
- warn_threshold_
- crit_threshold_
- warn_penalty_
- crit_penalty_
Default value is NULL.
modparam("qrouting", "extra_stats", "+mos/60; +r_factor; -503_replies/100")min_samples_asr (integer)
Section titled “min_samples_asr (integer)”The minimally accepted amount of sampled ASR statistics for each (prefix, destination) pair before they can be taken into account. As long as the number of samples stays below this limit, the ASR statistic of the pair is assumed to be healthy.
Default value is 30.
modparam("qrouting", "min_samples_asr", 50)min_samples_ccr (integer)
Section titled “min_samples_ccr (integer)”The minimally accepted amount of sampled CCR statistics for each (prefix, destination) pair before they can be taken into account. As long as the number of samples stays below this limit, the CCR statistic of the pair is assumed to be healthy.
Default value is 30.
modparam("qrouting", "min_samples_ccr", 50)min_samples_pdd (integer)
Section titled “min_samples_pdd (integer)”The minimally accepted amount of sampled PDD statistics for each (prefix, destination) pair before they can be taken into account. As long as the number of samples stays below this limit, the PDD statistic of the pair is assumed to be healthy.
Default value is 10.
modparam("qrouting", "min_samples_pdd", 15)min_samples_ast (integer)
Section titled “min_samples_ast (integer)”The minimally accepted amount of sampled AST statistics for each (prefix, destination) pair before they can be taken into account. As long as the number of samples stays below this limit, the AST statistic of the pair is assumed to be healthy.
Default value is 10.
modparam("qrouting", "min_samples_ast", 15)min_samples_acd (integer)
Section titled “min_samples_acd (integer)”The minimally accepted amount of sampled ACD statistics for each (prefix, destination) pair before they can be taken into account. As long as the number of samples stays below this limit, the ACD statistic of the pair is assumed to be healthy.
Default value is 20.
modparam("qrouting", "min_samples_acd", 30)event_bad_dst_threshold (string)
Section titled “event_bad_dst_threshold (string)”The minimally accepted quality of a (prefix, destination) combination, given as a quoted floating point number in the [0, 1] interval. Whenever a (prefix, destination) combination receives a score below this threshold, the E QROUTING BAD DST event will be triggered.
Default value is NULL (not set).
modparam("qrouting", "event_bad_dst_threshold", "0.5")decimal_digits (string)
Section titled “decimal_digits (string)”The amount of decimal digits to use in logging or MI output.
Default value is 2.
modparam("qrouting", "decimal_digits", 4)Exported Functions
Section titled “Exported Functions”qr_set_xstat(rule_id, gw_name, stat_name, inc_by, [part], [inc_total])
Section titled “qr_set_xstat(rule_id, gw_name, stat_name, inc_by, [part], [inc_total])”Provide a new sample value for an extra statistic on a given (prefix, gateway) combination. Extra statistics may be defined using the extra stats module parameter.
Parameters:
- rule_id (integer) - database id of the drouting rule holding the prefix and its destinations
- gw_name (string) - gateway to account the statistic for. The gateway must be part of the above rule’s destinations.
- stat_name (string) - statistic to account
- inc_by (string) - quoted floating point number, representing the amount to add to the stat
- part (string, optional, default: ‘Default’) - the drouting partition to use
- inc_total (string, optional, default: 1) - the amount to add to the total stat counter. Usually, this value should be 1, but it may make sense to set it to 0 when a custom statistic needs to be set a 2nd, 3rd, etc. time across the duration of the same established call.
This function can be used from any route.
# the MoS is set exactly once per call, so we can omit "inc_total"$var(rule_id) = 1574;$var(gw_name) = "GW-28";$var(mos_score) = "4.28";qr_set_xstat($var(rule_id), $var(gw_name), "mos", $var(mos_score));qr_disable_dst(rule_id, dst_name, [part])
Section titled “qr_disable_dst(rule_id, dst_name, [part])”Within a given routing rule, temporarily remove the given gateway or carrier from routing, until they are re-enabled via qr enable dst or mi qr enable dst. The removal effect will be lost on an OpenSIPS restart.
Parameters:
- rule_id (integer) - database id of the drouting rule
- dst_name (string) - gateway or carrier to disable
- part (string, optional) - drouting partition
This function can be used from any route.
# the signaling quality for @rule_id through @dst_name is degrading, remove it!event_route [E_QROUTING_BAD_DST]{ qr_disable_dst($param(rule_id), $param(dst_name), $param(partition));}qr_enable_dst(rule_id, dst_name, [part])
Section titled “qr_enable_dst(rule_id, dst_name, [part])”Within a given routing rule, re-introduce the given gateway or carrier into the routing process.
Parameters:
- rule_id (integer) - database id of the drouting rule
- dst_name (string) - gateway or carrier to disable
- part (string, optional) - drouting partition
This function can be used from any route.
# the ban has expired, let's re-enable this gateway and see how it behavesqr_enable_dst($param(rule_id), $param(dst_name), $param(partition));Exported MI Functions
Section titled “Exported MI Functions”qr_reload
Section titled “qr_reload”Reload all quality-based routing rules from the SQL database.
MI FIFO Command Format:
opensips-cli -x mi qr_reloadqr_status
Section titled “qr_status”Inspect the signaling quality statistics of the current history span for all drouting gateways in all partitions, with various levels of filtering.
Parameters:
- partition (optional) - a specific drouting partition to list statistics for
- rule_id (optional) - a specific drouting rule database id to list statistics for
- dst_name (optional) - a specific gateway or carrier name to list statistics for
MI FIFO Command Format:
opensips-cli -x mi qr_statusopensips-cli -x mi qr_status pstnopensips-cli -x mi qr_status pstn 11 MY-GW-3opensips-cli -x mi qr_status pstn 17 MY-CARR-7qr_disable_dst
Section titled “qr_disable_dst”Within a given routing rule, temporarily remove the given gateway or carrier from routing, until they are re-enabled manually. The removal effect will be lost on an OpenSIPS restart.
Parameters:
- partition (optional) - drouting partition
- rule_id - database id of the drouting rule
- dst_name - gateway or carrier to disable
MI FIFO Command Format:
opensips-cli -x mi qr_disable_dst 14 MY-CARR-7opensips-cli -x mi qr_disable_dst pstn 81 MY-GW-3qr_enable_dst
Section titled “qr_enable_dst”Within a given routing rule, re-introduce the given gateway or carrier into the routing process.
Parameters:
- partition (optional) - drouting partition
- rule_id - database id of the drouting rule
- dst_name - gateway or carrier to enable
MI FIFO Command Format:
opensips-cli -x mi qr_enable_dst 14 MY-CARR-7opensips-cli -x mi qr_enable_dst pstn 81 MY-GW-3Exported Events
Section titled “Exported Events”E_QROUTING_BAD_DST
Section titled “E_QROUTING_BAD_DST”This event may be raised during routing, asynchronously, whenever the score of a (prefix, destination) pair falls below event bad dst threshold.
Parameters:
- partition - drouting partition name
- rule_id - database id of the drouting rule
- dst_name - name of the concerned gateway or carrier
Contributors
Section titled “Contributors”By Commit Statistics
Section titled “By Commit Statistics”Top contributors by DevScore(1), authored commits(2) and lines added/removed(3)
| # | Name | DevScore | Commits | Lines++ | Lines— |
|---|---|---|---|---|---|
| 1. | Liviu Chircu (@liviuchircu) | 148 | 60 | 4865 | 2804 |
| 2. | Mihai Tiganus (@tallicamike) | 52 | 15 | 3078 | 632 |
| 3. | Stefan Darius (@dariusstefan) | 15 | 5 | 717 | 154 |
| 4. | Bogdan-Andrei Iancu (@bogdan-iancu) | 4 | 2 | 1 | 4 |
| 5. | Razvan Crainea (@razvancrainea) | 4 | 2 | 1 | 3 |
| 6. | Maksym Sobolyev (@sobomax) | 3 | 1 | 1 | 1 |
| 7. | Zero King (@l2dy) | 3 | 1 | 1 | 1 |
(1) DevScore = author_commits + author_lines_added / (project_lines_added / project_commits) + author_lines_deleted / (project_lines_deleted / project_commits)
(2) including any documentation-related commits, excluding merge commits
(3) ignoring whitespace edits, renamed files and auto-generated files
By Commit Activity
Section titled “By Commit Activity”| # | Name | Commit Activity |
|---|---|---|
| 1. | Bogdan-Andrei Iancu (@bogdan-iancu) | Mar 2020 - Jul 2026 |
| 2. | Stefan Darius (@dariusstefan) | Jun 2026 - Jul 2026 |
| 3. | Razvan Crainea (@razvancrainea) | Feb 2020 - Jun 2026 |
| 4. | Liviu Chircu (@liviuchircu) | Jan 2020 - Mar 2021 |
| 5. | Maksym Sobolyev (@sobomax) | Oct 2020 - Oct 2020 |
| 6. | Zero King (@l2dy) | Mar 2020 - Mar 2020 |
| 7. | Mihai Tiganus (@tallicamike) | Aug 2014 - Nov 2014 |
(1) including any documentation-related commits, excluding merge commits
Documentation
Section titled “Documentation”Contributors
Section titled “Contributors”Last edited by: Razvan Crainea (@razvancrainea), Liviu Chircu (@liviuchircu).
License
Section titled “License”All documentation files (i.e. .md extension) are licensed under the Creative Common License 4.0