Hi List
With the dispatcher module, you can use different ways of load balanced and weighted serial or parallel forking.
Is there a corresponding way to achieve load balanced serial forking to a destination set loaded from registered locations?
Use case:
Customer with a high availability set-up has two redundant PBX registered to the same AoR.
Calls can not be sent in parallel as this would generate two concurrent calls to the end device but call should be distributed evenly between the two contacts registered with that AoR.
Mit freundlichen Grüssen
-Benoît Panizzon-
Hi,
On Dec 9, 2024, at 3:51 am, Benoit Panizzon via sr-users sr-users@lists.kamailio.org wrote:
Hi List
With the dispatcher module, you can use different ways of load balanced and weighted serial or parallel forking.
Is there a corresponding way to achieve load balanced serial forking to a destination set loaded from registered locations?
Use case:
Customer with a high availability set-up has two redundant PBX registered to the same AoR.
Calls can not be sent in parallel as this would generate two concurrent calls to the end device but call should be distributed evenly between the two contacts registered with that AoR.
Yes, there is such a use-case, but it does not require `dispatcher`. You may use the mode=1 argument to t_load_contacts() instead, provided the devices are registered with equal q= values.
https://kamailio.org/docs/modules/5.8.x/modules/tm.html#idm1307
i.e.
route[REGISTRAR_SERIAL_TRY] { if(!lookup("location")) { send_reply("404", "Not Found"); exit; }
t_load_contacts(1); t_next_contacts();
# ... # t_on_failure("REGISTRAR_SERIAL_TRY_NEXT"), t_relay(), etc... }
failure_route[REGISTRAR_SERIAL_TRY_NEXT] { if(t_is_canceled()) exit;
if(!t_next_contacts()) { send_reply("408", "Request Timeout"); exit; }
t_on_failure("REGISTRAR_SERIAL_TRY_NEXT"); t_relay(); }
Hi Alex
Yes, there is such a use-case, but it does not require `dispatcher`. You may use the mode=1 argument to t_load_contacts() instead, provided the devices are registered with equal q= values.
https://kamailio.org/docs/modules/5.8.x/modules/tm.html#idm1307
Thank you! t_load_contacts => mode 1 sounds like what I was looking for. I guess I have some lab testing to do in the next couple of days ;)
Now I only miss the last piece: If I want to branch a call to different contacts in different locations, how can I do this? At the moment I painfully use reg_fetch_contacts and loop with append_branch setting all kind of variables manually.
Would this work smoothly with t_load_contacts?
Assuming alice has two contacts and bob one in the location database.
modparam("tm|usrloc", "xavp_contact", "ulattrs")
lookup("location", "sip:alice@example.com"); t_load_contacts(1); lookup("location", "sip:bob@example.com"); t_load_contacts(1);
Will this result in all 3 contacts being present in the XAVP so I could fail to the next one for serial balanced forking (mode 1) and alert all three of them if using t_load_contacts(0) and all having the same q value?
Mit freundlichen Grüssen
-Benoît Panizzon-
Hi Benoit,
On Dec 9, 2024, at 8:35 am, Benoit Panizzon benoit.panizzon@imp.ch wrote:
Would this work smoothly with t_load_contacts?
Assuming alice has two contacts and bob one in the location database.
modparam("tm|usrloc", "xavp_contact", "ulattrs")
lookup("location", "sip:alice@example.com"); t_load_contacts(1); lookup("location", "sip:bob@example.com"); t_load_contacts(1);
Will this result in all 3 contacts being present in the XAVP so I could fail to the next one for serial balanced forking (mode 1) and alert all three of them if using t_load_contacts(0) and all having the same q value?
I think the proper thing to do is:
- Decide if you want to use serial or fan-out ringing mode;
- If serial, t_load_contacts(1), and then associated failover failure_route.
- If parallel, t_load_contacts(0).
Ensure that q-values are equal in both cases.
-- Alex
Hi Alex
Thank you again for your help.
To make this work, all contacts need the same q value.
But I have not figured out, how to set this q value.
I have a client, which is sending a q=0.5 attribute with the contact header. No matter what I attempt, this is the value which is put into the location database.
modparam("registrar", "xavp_cfg", "reg") modparam("registrar", "default_q", 300)
$xavp(reg=>q) = 400;
$var(saveuri) = "sip:" + $aU + "@" + $rd; $var(result) = save("location","0x00","$var(saveuri)");
What am I missing to make reg=>q work?
Mit freundlichen Grüssen
-Benoît Panizzon-
I'm not sure offhand how to forcefully override the q-value provided by the client. However, if you have two types of clients, (a) one that sends a q=0.5 value and (b) others that send no value, you can set default_q to 0.5.
https://kamailio.org/docs/modules/5.8.x/modules/registrar.html#idm161
-- Alex
On Dec 9, 2024, at 10:53 am, Benoit Panizzon benoit.panizzon@imp.ch wrote:
Hi Alex
Thank you again for your help.
To make this work, all contacts need the same q value.
But I have not figured out, how to set this q value.
I have a client, which is sending a q=0.5 attribute with the contact header. No matter what I attempt, this is the value which is put into the location database.
modparam("registrar", "xavp_cfg", "reg") modparam("registrar", "default_q", 300)
$xavp(reg=>q) = 400;
$var(saveuri) = "sip:" + $aU + "@" + $rd; $var(result) = save("location","0x00","$var(saveuri)");
What am I missing to make reg=>q work?
Mit freundlichen Grüssen
-Benoît Panizzon-
I m p r o W a r e A G - Leiter Commerce Kunden ______________________________________________________
Zurlindenstrasse 29 Tel +41 61 826 93 00 CH-4133 Pratteln Fax +41 61 826 93 01 Schweiz Web http://www.imp.ch ______________________________________________________
Hi Alex
I'm not sure offhand how to forcefully override the q-value provided by the client. However, if you have two types of clients, (a) one that sends a q=0.5 value and (b) others that send no value, you can set default_q to 0.5.
This is what I do for testing now. But if a client is sending a different q attribute, this will break thinks, so I guess there must be a way to override the value sent by the client.
The documentation mentions this should work:
modparam("registrar", "xavp_cfg", "reg") $xavp(reg=>q) = 500;
So maybe there are more prerequisites which I missed to make this work?
I also found an old notice in my config stating that setting $xavp(reg=>max_contacts) had no effect.
default_q only applies to clients registering without q attribute.
Also I fear that t_load_contacts() cleans the XAVP before loading the destination set obtained by lookup into it. Is there a way to prevent this? Is there another way to load contacts from multiple AoR into the destination set?
In my example I had:
AoR Alice with 2 contacts both q=0.5 AoR Bob with 1 contact q=0.5
modparam("tm", "contacts_avp", "tm_contacts") modparam("tm", "contact_flows_avp", "tm_contact_flows")
lookup("location", "sip:alice@example.com"); t_load_contacts(0); lookup("location", "sip:bob@example.com"); t_load_contacts(0);
t_on_branch("BR_TO_LOC"); route(RELAY);
I would expect to see parallel forking to 3 contacts. I observe only the call towards bob's contact.
I keep digging...
Mit freundlichen Grüssen
-Benoît Panizzon-
Hi
Short update on that topic...
Daniel hinted me to lookup_to_dset()
Indeed, calling this function multiple time, contrary to lookup(), does not overwrite the branches, but is adding the contacts from each lookup to the destination set.
So this does what I intended for parallel forking and serial forking only needs adding the failure route. I guess creating the branches in performed by t_next_contacts().
$var(i) = 0; while ($xavp(aor[$var(i)]) != $null) { lookup_to_dset($xavp(aor[$var(i)])); $var(i) = $var(i) + 1; } if (!t_load_contacts(0)) { xlog("L_ERR", "$cfg(route): ######### load_contacts failed\n"); sl_send_reply("500", "Server Internal Error - Cannot load contacts"); exit; }
xlog("L_INFO", "$cfg(route): Contacts loaded: $cnt($xavp(tm_contacts))\n");
if (!t_next_contacts()) { send_reply("480", "No contacts registered for any AoR"); exit; } route(RELAY);
Thank you for sharing
--- I'm SoCIaL, MayBe
El 13/12/2024 a las 4:50 a. m., Benoît Panizzon via sr-users escribió:
Hi
Short update on that topic...
Daniel hinted me to lookup_to_dset()
Indeed, calling this function multiple time, contrary to lookup(), does not overwrite the branches, but is adding the contacts from each lookup to the destination set.
So this does what I intended for parallel forking and serial forking only needs adding the failure route. I guess creating the branches in performed by t_next_contacts().
$var(i) = 0; while ($xavp(aor[$var(i)]) != $null) { lookup_to_dset($xavp(aor[$var(i)])); $var(i) = $var(i) + 1; } if (!t_load_contacts(0)) { xlog("L_ERR", "$cfg(route): ######### load_contacts failed\n"); sl_send_reply("500", "Server Internal Error - Cannot load contacts"); exit; }
xlog("L_INFO", "$cfg(route): Contacts loaded: $cnt($xavp(tm_contacts))\n");
if (!t_next_contacts()) { send_reply("480", "No contacts registered for any AoR"); exit; } route(RELAY);