1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
|
LCR(Least Cost Routing) Module
Juha Heinanen
Edited by
Juha Heinanen
Copyright 2005 Juha Heinanen
_________________________________________________________
Table of Contents
1. User's Guide
1.1. Overview
1.2. Dependencies
1.2.1. OpenSER modules
1.2.2. External libraries or applications
1.3. Exported Parameters
1.3.1. db_url (string)
1.3.2. gw_table (string)
1.3.3. gw_name_column (string)
1.3.4. ip_addr_column (string)
1.3.5. port_column (string)
1.3.6. uri_scheme_column (string)
1.3.7. transport_column (string)
1.3.8. grp_id_column (string)
1.3.9. lcr_table (string)
1.3.10. strip_column (string)
1.3.11. prefix_column (string)
1.3.12. from_uri_column (string)
1.3.13. priority_column (string)
1.3.14. gw_uri_avp (string)
1.3.15. ruri_user_avp (string)
1.3.16. contact_avp (string)
1.3.17. fr_inv_timer_avp (string)
1.3.18. fr_inv_timer (integer)
1.3.19. fr_inv_timer_next (integer)
1.3.20. rpid_avp (string)
1.3.21. db_mode (integer)
1.4. Exported Functions
1.4.1. load_gws(), load_gws(group-id)
1.4.2. next_gw()
1.4.3. from_gw(), from_gw(group-id)
1.4.4. to_gw(), to_gw(group-id)
1.4.5. load_contacts()
1.4.6. next_contacts()
1.5. FIFO Commands
1.5.1. lcr_reload
1.5.2. lcr_dump
1.6. Known Limitations
1.7. TODO
2. Developer's Guide
3. Frequently Asked Questions
List of Examples
1-1. Setting db_url module parameter
1-2. Setting gw_table module parameter
1-3. Setting gw_name_column module parameter
1-4. Setting ip_addr_column module parameter
1-5. Setting port_column module parameter
1-6. Setting uri_scheme_column module parameter
1-7. Setting transport_column module parameter
1-8. Setting grp_id_column module parameter
1-9. Setting lcr_table module parameter
1-10. Setting strip_column module parameter
1-11. Setting prefix_column module parameter
1-12. Setting from_uri_column module parameter
1-13. Setting priority_column module parameter
1-14. Setting gw_uri_avp module parameter
1-15. Setting ruri_user_avp module parameter
1-16. Setting contact_avp module parameter
1-17. Setting fr_inv_timer_avp module parameter
1-18. Setting fr_inv_timer module parameter
1-19. Setting fr_inv_timer_next module parameter
1-20. Setting rpid_avp module parameter
1-21. Setting db_mode module parameter
1-22. load_gws usage
1-23. load_gws usage with group-id
1-24. next_gw usage from a route block
1-25. next_gw usage from a failure route block
1-26. from_gw usage
1-27. from_gw usage with group-id
1-28. to_gw usage
1-29. to_gw usage with group-id
1-30. load_contacts usage
1-31. next_contacts usage from route block
1-32. next_contacts usage from failure route block
_________________________________________________________
Chapter 1. User's Guide
1.1. Overview
Least cost routing (LCR) module implements two related
capabilities:
* sequential forwarding of a request to one or more gateways
(functions load_gws and next_gw)
* sequential forwarding to contacts if they don't share the
the same qvalue (functions load_contacts and
next_contacts).
Gateway selection is based on caller's RPID URI (if available
in caller's RPID AVP after authentication) or From URI and
user part of Request-URI (telephone number). A gateway matches
a request if user part of Request-URI and "From" URI match the
prefix and From pattern of the gateway. Matching gateways are
then ordered for forwarding purpose (1) according to longest
user part match, (2) according to gateway's priority, and (3)
randomly.
Each gateway belongs to a gateway group either alone or among
other gateways. All gateways in a group share the same
priority.
Gateway and routing information is kept in two tables: gw and
lcr.
When a gateway is selected, the Request-URI user part is
stripped by the number of digits specified in the strip
parameter. Subsequently, the Request-URI is rewritten with
information from gw table: URI scheme, prefix, IP address,
port, and transport protocol. Valid URI scheme values are NULL
= sip, 1 = sip and 2 = sips. Prefix is appended in front of
Request-URI user part. Currently valid transport protocol
values are NULL = none, 1 = udp, 2 = tcp, and 3 = tls.
Table lcr contains prefix of user part of Request-URI, From
URI, gateway group id, and priority. From URI can contain
special characters % and _ matching any number of any
characters and any one character, respectively, if db_mod
parameter is set to 0. If db_mod parameter is set to 1, then
From URI is a regular expression.
In addition to gw and lcr tables there is third table gw_grp
that is used to associate names with gateway group ids.
_________________________________________________________
1.2. Dependencies
1.2.1. OpenSER modules
The following modules must be loaded before this module:
* TM module
* A database module like mysql, postgres or dbtext.
_________________________________________________________
1.2.2. External libraries or applications
The following libraries or applications must be installed
before running OpenSER with this module:
* none.
_________________________________________________________
1.3. Exported Parameters
1.3.1. db_url (string)
URL of the database table to be used.
Default value is
"mysql://openserro:openserro@localhost/openser".
Example 1-1. Setting db_url module parameter
...
modparam("lcr","db_url","mysql://muser:pwd@localhost/openser")
...
_________________________________________________________
1.3.2. gw_table (string)
Name of the table holding the gateways definitions.
Default value is "gw".
Example 1-2. Setting gw_table module parameter
...
modparam("lcr","gw_table","gw")
...
_________________________________________________________
1.3.3. gw_name_column (string)
Name of the column holding the gateway name.
Default value is "gw_name".
Example 1-3. Setting gw_name_column module parameter
...
modparam("lcr","gw_name_column","gw_name")
...
_________________________________________________________
1.3.4. ip_addr_column (string)
Name of the column holding the IP address of the gateway.
Default value is "ip_addr".
Example 1-4. Setting ip_addr_column module parameter
...
modparam("lcr","ip_addr_column","ip_addr")
...
_________________________________________________________
1.3.5. port_column (string)
Name of the column holding the port number of the gateway.
Default value is "port".
Example 1-5. Setting port_column module parameter
...
modparam("lcr","port_column","port")
...
_________________________________________________________
1.3.6. uri_scheme_column (string)
Name of the column holding the uri scheme of the gateway.
Default value is "uri_scheme".
Example 1-6. Setting uri_scheme_column module parameter
...
modparam("lcr","uri_scheme_column","scheme")
...
_________________________________________________________
1.3.7. transport_column (string)
Name of the column holding the transport type to be used for
the gateway.
Default value is "transport".
Example 1-7. Setting transport_column module parameter
...
modparam("lcr","transport_column","transport")
...
_________________________________________________________
1.3.8. grp_id_column (string)
Name of the column holding the group ID.
Default value is "grp_id".
Example 1-8. Setting grp_id_column module parameter
...
modparam("lcr","grp_id_column","grp_id")
...
_________________________________________________________
1.3.9. lcr_table (string)
Name of the table holding the LCR rules.
Default value is "lcr".
Example 1-9. Setting lcr_table module parameter
...
modparam("lcr","lcr_table","lcr")
...
_________________________________________________________
1.3.10. strip_column (string)
Name of the column holding the number of digits to strip from
the RURI before applying the prefix.
Default value is "strip".
Example 1-10. Setting strip_column module parameter
...
modparam("lcr","strip_column","strip")
...
_________________________________________________________
1.3.11. prefix_column (string)
Name of the column holding the RURI(destination) prefix.
Default value is "prefix".
Example 1-11. Setting prefix_column module parameter
...
modparam("lcr","prefix_column","prefix")
...
_________________________________________________________
1.3.12. from_uri_column (string)
Name of the column holding the FROM (source) URI.
Default value is "from_uri".
Example 1-12. Setting from_uri_column module parameter
...
modparam("lcr","from_uri_column","from_uri")
...
_________________________________________________________
1.3.13. priority_column (string)
Name of the column holding the priority of the rule.
Default value is "priority".
Example 1-13. Setting priority_column module parameter
...
modparam("lcr","priority_column","priority")
...
_________________________________________________________
1.3.14. gw_uri_avp (string)
Overrides the name of the AVP containing URI scheme, host,
port, and transport of a gateway. If the string name of the
AVP contains only digits, the name of the AVP is integer value
of the string.
Default value is "1400".
Example 1-14. Setting gw_uri_avp module parameter
...
modparam("lcr","gw_uri_avp","1400")
...
_________________________________________________________
1.3.15. ruri_user_avp (string)
Overrides the name of the AVP containing user part of
Request-URI after the first next_gw() call. If the string name
of the AVP contains only digits, the name of the AVP is
integer value of the string.
Default value is "1402".
Example 1-15. Setting ruri_user_avp module parameter
...
modparam("lcr","ruri_user_avp","500")
...
_________________________________________________________
1.3.16. contact_avp (string)
Overrides the name of the AVP containing the contact. If the
string name of the AVP contains only digits, the name of the
AVP is integer value of the string.
Default value is "1401".
Example 1-16. Setting contact_avp module parameter
...
modparam("lcr","contact_avp","1401")
...
_________________________________________________________
1.3.17. fr_inv_timer_avp (string)
Overrides the name of the AVP carrying the Final Response
timeout for INVITEs.
Default value is "fr_inv_timer_avp".
Example 1-17. Setting fr_inv_timer_avp module parameter
...
modparam("lcr","fr_inv_timer_avp","fr_inv_timer_avp")
...
_________________________________________________________
1.3.18. fr_inv_timer (integer)
Sets the value of the fist INVITE's Final Response timeout to
be used during sequential forwarding:
Default value is 90.
Example 1-18. Setting fr_inv_timer module parameter
...
modparam("lcr","fr_inv_timer",90)
...
_________________________________________________________
1.3.19. fr_inv_timer_next (integer)
Sets the value of the next INVITE's Final Response timeouts to
be used during sequential forwarding:
Function next_contacts() sets tm fr_inv_timer to
fr_inv_timer_next value if, after next contacts, there are
still lower qvalue contacts available, and to fr_inv_timer
value if next contacts are the last ones left.
Default value is 30.
Example 1-19. Setting fr_inv_timer_next module parameter
...
modparam("lcr","fr_inv_timer_next",30)
...
_________________________________________________________
1.3.20. rpid_avp (string)
Sets the string name of the AVP containing the RPID.
Default value is "rpid".
Example 1-20. Setting rpid_avp module parameter
...
modparam("lcr","rpid_avp","rpid")
...
_________________________________________________________
1.3.21. db_mode (integer)
Sets the database mode of operating:
* 0 : no-caching - a db lookup is performed during each
load_gws()
* 1 : regexp are used for from_uri; no db lookup is
performed during load_gws(), the DB content is cached into
memory;
Default value is "1".
Example 1-21. Setting db_mode module parameter
...
modparam("lcr","db_mode",0)
...
_________________________________________________________
1.4. Exported Functions
1.4.1. load_gws(), load_gws(group-id)
Loads URI schemes, addresses, ports, and transports of
gateways that match user part of Request-URI to gw_uri_avp
AVPs (see Overview section). If an optional group-id is
specified, only gateways belonging to this group are loaded.
Returns 1 or -1 depending on success.
This function can be used from REQUEST_ROUTE.
Example 1-22. load_gws usage
...
if (!load_gws()) {
sl_send_reply("500", "Server Internal Error - Cannot load gatew
ays");
break;
};
...
Example 1-23. load_gws usage with group-id
...
if (!load_gws("1")) {
sl_send_reply("500", "Server Internal Error - Cannot load gatew
ays from group 1");
break;
};
...
_________________________________________________________
1.4.2. next_gw()
If called from a route block, replaces URI scheme, host, port,
and transport of Request-URI by the values stored in first
gw_uri_avp AVP and destroys that AVP. Saves user part of
Request-URI into ruri_user_avp AVP for use in subsequent
next_gw() calls.
If called from a failure route block, appends a new branch to
request, where URI scheme, host, port, and transport of
Request-URI is replaced by the values stored in the first
gw_uri_avp AVP and destroys that AVP. Request-URI user is
taken from ruri_user_avp AVP.
Returns 1 on success and -1 if there were no gateways left or
if an error occurred (see syslog).
Must be preceded by successful load_gws() call.
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
Example 1-24. next_gw usage from a route block
...
if (!next_gw()) {
sl_send_reply("503", "Service not available - No gateways");
break;
};
...
Example 1-25. next_gw usage from a failure route block
...
if (!next_gw()) {
t_reply("503", "Service not available - No more gateways");
break;
};
...
_________________________________________________________
1.4.3. from_gw(), from_gw(group-id)
Checks if request came from IP address of a gateway. If an
optional group-id is given, only gateways belonging to this
group are checked.
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE,
ONREPLY_ROUTE.
Example 1-26. from_gw usage
...
if (from_gw()) {
...
break;
};
...
Example 1-27. from_gw usage with group-id
...
if (from_gw("1")) {
...
break;
};
...
_________________________________________________________
1.4.4. to_gw(), to_gw(group-id)
Checks if in-dialog request goes to a gateway. If an optional
group-id is given, only gateways belonging to this group are
checked.
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
Example 1-28. to_gw usage
...
if (to_gw()) {
...
break;
};
...
Example 1-29. to_gw usage with group-id
...
if (to_gw("1")) {
...
break;
};
...
_________________________________________________________
1.4.5. load_contacts()
Loads contacts in destination set in increasing qvalue order
as values of lcr_contact AVP. If all contacts in the
destination set have the same qvalue, load_contacts() does not
do anything thus minimizing performance impact of sequential
forking capability when it is not needed. Returns 1 if loading
of contacts succeeded or there was nothing to do. Returns -1
on error (see syslog).
This function can be used from REQUEST_ROUTE.
Example 1-30. load_contacts usage
...
if (!load_contacts()) {
sl_send_reply("500", "Server Internal Error - Cannot load conta
cts");
break;
};
...
_________________________________________________________
1.4.6. next_contacts()
If called from a route block, replaces Request-URI with the
first lcr_contact AVP value, adds the remaining lcr_contact
AVP values with the same qvalue as branches, and destroys
those AVPs. It does nothing if there are no lcr_contact AVPs.
Returns 1 if there were no errors and -1 if an error occurred
(see syslog).
If called from a failure route block, adds the first
lcr_contact AVP value and all following lcr_contact AVP values
with the same qvalue as new branches to request and destroys
those AVPs. Returns 1 if new branches were successfully added
and -1 on error (see syslog) or if there were no more
lcr_contact AVPs.
Must be preceded by successful load_contacts() call.
This function can be used from REQUEST_ROUTE, FAILURE_ROUTE.
Example 1-31. next_contacts usage from route block
...
if (!next_contacts()) {
sl_send_reply("500", "Server Internal Error");
break;
} else {
t_relay();
};
...
Example 1-32. next_contacts usage from failure route block
if (next_contacts()) {
t_relay();
};
_________________________________________________________
1.5. FIFO Commands
1.5.1. lcr_reload
Causes lcr module to re-read the contents of gateway table
into memory.
_________________________________________________________
1.5.2. lcr_dump
Causes lcr module to dump the contents of its in-memory
gateway table.
_________________________________________________________
1.6. Known Limitations
There is an unlikely race condition on lcr reload. If a
process uses in memory gw table, which is reloaded at the same
time twice through FIFO, the second reload will delete the
original table still in use by the process.
_________________________________________________________
1.7. TODO
Function load_gws() currently makes an SQL query for the
matching gateways. In order to avoid the query, also lcr table
should be read into memory and the corresponding query should
be rewritten in C.
_________________________________________________________
Chapter 2. Developer's Guide
The module does not provide any API to use in other OpenSER
modules.
_________________________________________________________
Chapter 3. Frequently Asked Questions
3.1. Where can I find more about OpenSER?
3.2. Where can I post a question about this module?
3.3. How can I report a bug?
3.1. Where can I find more about OpenSER?
Take a look at http://openser.org/.
3.2. Where can I post a question about this module?
First at all check if your question was already answered on
one of our mailing lists:
* User Mailing List -
http://openser.org/cgi-bin/mailman/listinfo/users
* Developer Mailing List -
http://openser.org/cgi-bin/mailman/listinfo/devel
E-mails regarding any stable OpenSER release should be sent to
<users@openser.org> and e-mails regarding development versions
should be sent to <devel@openser.org>.
If you want to keep the mail private, send it to
<team@openser.org>.
3.3. How can I report a bug?
Please follow the guidelines provided at:
http://sourceforge.net/tracker/?group_id=139143.
|