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