Hi,
To show a possible scenario for the new Path features, consider the following setup:
[UAC] <--> (NAT) <-+-> [LB] <--+--> [REGn] | | [Peer-Proxies] <---+ +--> [PRXn] <-- DNS-SRV --> [GWn]
Where UAC are the clients (optionally behind NAT), LB is a SIP loadbalancer based on OpenSER, REGn is a federation of Registrars and PRXn a federation of Proxies, all using the new cacheless usrloc feature of OpenSER. GWn is a federation of SIP GWs for PSTN termination, and Peer-Proxies are other SIP service providers.
LB is the outbound proxy of the UACs, and the registrars and proxies behind it are in a private LAN. LB uses the dispatcher module for load balancing and failover handling of these nodes. By using the cacheless usrloc feature in combination with a mysql cluster, registrars and proxies can scale up to an arbitrary number of nodes. Since only one public IP can be advertised to the clients for proper NAT traversal, LB has to be clustered in an active/passive way using IP-takeover for high-availability. If the LB becomes the bottleneck, a second LB pair can be set up and been advertised as outbound proxy to new UACs, using the same proxy/registrar federation as backend. But since LB doesn't need to access a DB or perform much processing, a quite high CPS rate can be expected (not measured yet though).
An example-config for the LB may look like that (only relevant parts shown):
#+ ... loadmodule "dispatcher.so" loadmodule "path.so"
modparam("dispatcher", "list_file", "/etc/dispatcher.lst") modparam("path", "use_received", 1) ... route { ... if(method == "REGISTER") { if( /* NAT check here */ ) { ... add_path_received("loadbalancer"); ... } else { ... add_path("loadbalancer"); ... } ds_select_dst( /* select a registrar here */ ); } else if(method == "INVITE") { ... ds_select_dst( /* select a proxy here */ ); record_route(); ... } ... }
/* * failure routes for failover, reply-routes for NAT-handling etc. * go here */ #-
add_path() ensures, that subsequent requests (INVITES etc.) from the proxy are routed via the same loadbalancer, which is used by the UAC as outbound proxy, and use_received=1 lets requests from backend proxies route to the NATed address if available.
The config for the registrars is straight-forward, except for the registrar-module parameters:
#+ ... modparam("registrar", "use_path", 1) modparam("registrar", "path_mode", 0) modparam("registrar", "path_use_received", 1) ... #-
This ensures that the Path header is recognized (use_path=1), the Path header is never included in the reply (path_mode=0), and the received-parameter of the first Path URI is saved as received-value in usrloc, if available.
Note, that nat-pinging is not properly supported by this setup (as noted before), because UACs have to be pinged with the source-address set to the address of the LB. This could either be accomplished by using OPTION for nat-ping and route that request according to the stored Path header (will put a lot of unnecessary load to the LB), or let the LB natping the UACs (also unnecessary load for the LB, and LB would require access to usrloc), or use an external application which spoofs the LB address and directly fetches the received-address from the location table (used in our setup and seems to be the most flexible and scalable way for me).
Hope, this sheds some light on the usefulness of the new Path features. Please be aware that this is currently a proof-of-concept implementation for a highly scalable SIP system using openser, and is not in production yet. So comments are highly welcome.
Cheers, Andy