transaction: refactor callref allocation
Each transaction has a field called 'callref', that should contain an unique identifier. This identifier is being assigned either by OsmoMSC itself, either by an external application (e.g. LCR), and is used to distinguish between multiple allocated transactions.
In case of a new callref generation on the MSC side, there are the following sources for that:
$ git grep "static uint32_t new_callref" src/libmsc/gsm_04_08.c:static uint32_t new_callref = 0x80000001; src/libmsc/gsm_04_11.c:static uint32_t new_callref = 0x40000001; src/libmsc/mncc_builtin.c:static uint32_t new_callref = 0x00000001;
So, we have a few ranges for different types of communication:
- from 0x00000001 to 0x40000000 - Call Control, internal MNCC;
- from 0x40000001 to 0x80000000 - SMS messages;
- from 0x80000001 to 0xffffffff - Call Control, external MNCC;
And this is how a new 'callref' value is generated:
I see the following problems:
1) Imagine that we have a network, which is running for some long time. What if the amount of calls ever made would reach 0x40000000? The next values will be 0x40000001, 0x40000002, 0x40000003, etc. At some point, this may result into collisions, e.g. two transactions with same 'callref' value.
Possible solution: instead of doing `new_callref++` manually, create a function (e.g. trans_gen_ref), which would prevent overlaps between ranges, and flush the source to initial value.
2) The trans_alloc(), which is used to allocate a new transactions, doesn't check if passed 'callref' value is not used. In other words, it is possible to allocate a few transactions with not unique 'callref'. In this case the trans_find_by_callref() would work incorrectly.
Possible solution: before allocation, check if given 'callref' is already used.
3) The 'callref' as a field name itself looks/sounds like something call related, while this feature will be also used as soon as we implement SMS and SS/USSD over GSUP. It would be better to rename it to something more generic, e.g. just 'ref'.
4) Both sides, i.e. MSC and an external application, are involved in 'callref' generation. There is no master-slave relation... This may result in a situation, when an external application asks to allocate a new transaction with 'callref', which is already used.
Possible solution: inspire by GSM TS 04.07, section 11.2.3 "Transaction identifier" and introduce the direction bit. Probably, this can be a bit simplified, e.g. '0' means allocated by the MSC itself, '1' - by an external application.
On a related note: CallRef is sent as part of LCLS-related config to BSC where it's used to match related call legs. Current allocation scheme makes it hard because of the different prefixes used by CC and MNCC code. I've worked around this by dropping prefix byte and using remainder for LCLS but it's a race-prone hack. When fixing this we should definitely take LCLS into consideration.