Skip to content

Commit

Permalink
usrloc: Learn the active node AoR rlabel (as backup node)
Browse files Browse the repository at this point in the history
When using timer-based contact cleanup in Active/Passive user location
scenarios, the two timers may run in such a way that the backup node
still has a given AoR, while the AoR does _not_ exist on the active
node...

Now, if a phone registers, the backup node complains that the
replicated AoR's auto-generated rlabel differs from its own one, since
the old AoR has yet to be cleaned up.  And as long as the AoR has no
contacts, we can safely re-learn (overwrite) the AoR's rlabel on the
backup node and fix this race condition.

Credits to Giovanni Maruzzelli for reporting this issue and providing
accurate debug logs!

Fixes #2524
  • Loading branch information
liviuchircu committed Aug 13, 2021
1 parent 15321ba commit 24ec0d2
Showing 1 changed file with 23 additions and 6 deletions.
29 changes: 23 additions & 6 deletions modules/usrloc/ul_cluster.c
Expand Up @@ -504,7 +504,7 @@ static int receive_ucontact_insert(bin_packet_t *packet)
user_agent, path, attr, st, sock, kv_str;
udomain_t *domain;
urecord_t *record;
ucontact_t *contact;
ucontact_t *contact, *ct;
int rc, port, proto, sl;
unsigned short _, clabel;
unsigned int rlabel;
Expand Down Expand Up @@ -603,13 +603,30 @@ static int receive_ucontact_insert(bin_packet_t *packet)

record->label = rlabel;
sl = record->aorhash & (domain->size - 1);
if (domain->table[sl].next_label <= record->label)
domain->table[sl].next_label = record->label + 1;
if (domain->table[sl].next_label <= rlabel)
domain->table[sl].next_label = rlabel + 1;
}

if (record->label != rlabel)
LM_BUG("replicated ct insert: differring rlabels! (ci: '%.*s')",
callid.len, callid.s);
if (record->label != rlabel) {
int has_good_cts = 0;

for (ct = record->contacts; ct; ct = ct->next)
if (ct->expires != UL_EXPIRED_TIME) {
has_good_cts = 1;
break;
}

if (has_good_cts) {
LM_BUG("differring rlabels (%u vs. %u, ci: '%.*s')",
record->label, rlabel, callid.len, callid.s);
} else {
/* no contacts -> it's safe to inherit the active node's rlabel */
record->label = rlabel;
sl = record->aorhash & (domain->size - 1);
if (domain->table[sl].next_label <= rlabel)
domain->table[sl].next_label = rlabel + 1;
}
}

if (record->next_clabel <= clabel)
record->next_clabel = CLABEL_INC_AND_TEST(clabel);
Expand Down

0 comments on commit 24ec0d2

Please sign in to comment.