Age | Commit message (Collapse) | Author | Files | Lines |
|
3GPP TS 49.008 '4.3 Roles of MSC-A, MSC-I and MSC-T' defines distinct roles:
- MSC-A is responsible for managing subscribers,
- MSC-I is the gateway to the RAN.
- MSC-T is a second transitory gateway to another RAN during Handover.
After inter-MSC Handover, the MSC-I is handled by a remote MSC instance, while
the original MSC-A retains the responsibility of subscriber management.
MSC-T exists in this patch but is not yet used, since Handover is only prepared
for, not yet implemented.
Facilitate Inter-MSC and inter-BSC Handover by the same internal split of MSC
roles.
Compared to inter-MSC Handover, mere inter-BSC has the obvious simplifications:
- all of MSC-A, MSC-I and MSC-T roles will be served by the same osmo-msc
instance,
- messages between MSC-A and MSC-{I,T} don't need to be routed via E-interface
(GSUP),
- no call routing between MSC-A and -I via MNCC necessary.
This is the largest code bomb I have submitted, ever. Out of principle, I
apologize to everyone trying to read this as a whole. Unfortunately, I see no
sense in trying to split this patch into smaller bits. It would be a huge
amount of work to introduce these changes in separate chunks, especially if
each should in turn be useful and pass all test suites. So, unfortunately, we
are stuck with this code bomb.
The following are some details and rationale for this rather huge refactoring:
* separate MSC subscriber management from ran_conn
struct ran_conn is reduced from the pivotal subscriber management entity it has
been so far to a mere storage for an SCCP connection ID and an MSC subscriber
reference.
The new pivotal subscriber management entity is struct msc_a -- struct msub
lists the msc_a, msc_i, msc_t roles, the vast majority of code paths however
use msc_a, since MSC-A is where all the interesting stuff happens.
Before handover, msc_i is an FSM implementation that encodes to the local
ran_conn. After inter-MSC Handover, msc_i is a compatible but different FSM
implementation that instead forwards via/from GSUP. Same goes for the msc_a
struct: if osmo-msc is the MSC-I "RAN proxy" for a remote MSC-A role, the
msc_a->fi is an FSM implementation that merely forwards via/from GSUP.
* New SCCP implementation for RAN access
To be able to forward BSSAP and RANAP messages via the GSUP interface, the
individual message layers need to be cleanly separated. The IuCS implementation
used until now (iu_client from libosmo-ranap) did not provide this level of
separation, and needed a complete rewrite. It was trivial to implement this in
such a way that both BSSAP and RANAP can be handled by the same SCCP code,
hence the new SCCP-RAN layer also replaces BSSAP handling.
sccp_ran.h: struct sccp_ran_inst provides an abstract handler for incoming RAN
connections. A set of callback functions provides implementation specific
details.
* RAN Abstraction (BSSAP vs. RANAP)
The common SCCP implementation did set the theme for the remaining refactoring:
make all other MSC code paths entirely RAN-implementation-agnostic.
ran_infra.c provides data structures that list RAN implementation specifics,
from logging to RAN de-/encoding to SCCP callbacks and timers. A ran_infra
pointer hence allows complete abstraction of RAN implementations:
- managing connected RAN peers (BSC, RNC) in ran_peer.c,
- classifying and de-/encoding RAN PDUs,
- recording connected LACs and cell IDs and sending out Paging requests to
matching RAN peers.
* RAN RESET now also for RANAP
ran_peer.c absorbs the reset_fsm from a_reset.c; in consequence, RANAP also
supports proper RESET semantics now. Hence osmo-hnbgw now also needs to provide
proper RESET handling, which it so far duly ignores. (TODO)
* RAN de-/encoding abstraction
The RAN abstraction mentioned above serves not only to separate RANAP and BSSAP
implementations transparently, but also to be able to optionally handle RAN on
distinct levels. Before Handover, all RAN messages are handled by the MSC-A
role. However, after an inter-MSC Handover, a standalone MSC-I will need to
decode RAN PDUs, at least in order to manage Assignment of RTP streams between
BSS/RNC and MNCC call forwarding.
ran_msg.h provides a common API with abstraction for:
- receiving events from RAN, i.e. passing RAN decode from the BSC/RNC and
MS/UE: struct ran_dec_msg represents RAN messages decoded from either BSSMAP
or RANAP;
- sending RAN events: ran_enc_msg is the counterpart to compose RAN messages
that should be encoded to either BSSMAP or RANAP and passed down to the
BSC/RNC and MS/UE.
The RAN-specific implementations are completely contained by ran_msg_a.c and
ran_msg_iu.c.
In particular, Assignment and Ciphering have so far been distinct code paths
for BSSAP and RANAP, with switch(via_ran){...} statements all over the place.
Using RAN_DEC_* and RAN_ENC_* abstractions, these are now completely unified.
Note that SGs does not qualify for RAN abstraction: the SGs interface always
remains with the MSC-A role, and SGs messages follow quite distinct semantics
from the fairly similar GERAN and UTRAN.
* MGW and RTP stream management
So far, managing MGW endpoints via MGCP was tightly glued in-between
GSM-04.08-CC on the one and MNCC on the other side. Prepare for switching RTP
streams between different RAN peers by moving to object-oriented
implementations: implement struct call_leg and struct rtp_stream with distinct
FSMs each. For MGW communication, use the osmo_mgcpc_ep API that has originated
from osmo-bsc and recently moved to libosmo-mgcp-client for this purpose.
Instead of implementing a sequence of events with code duplication for the RAN
and CN sides, the idea is to manage each RTP stream separately by firing and
receiving events as soon as codecs and RTP ports are negotiated, and letting
the individual FSMs take care of the MGW management "asynchronously". The
caller provides event IDs and an FSM instance that should be notified of RTP
stream setup progress. Hence it becomes possible to reconnect RTP streams from
one GSM-04.08-CC to another (inter-BSC Handover) or between CC and MNCC RTP
peers (inter-MSC Handover) without duplicating the MGCP code for each
transition.
The number of FSM implementations used for MGCP handling may seem a bit of an
overkill. But in fact, the number of perspectives on RTP forwarding are far
from trivial:
- an MGW endpoint is an entity with N connections, and MGCP "sessions" for
configuring them by talking to the MGW;
- an RTP stream is a remote peer connected to one of the endpoint's
connections, which is asynchronously notified of codec and RTP port choices;
- a call leg is the higher level view on either an MT or MO side of a voice
call, a combination of two RTP streams to forward between two remote peers.
BSC MGW PBX
CI CI
[MGW-endpoint]
[--rtp_stream--] [--rtp_stream--]
[----------------call_leg----------------]
* Use counts
Introduce using the new osmo_use_count API added to libosmocore for this
purpose. Each use token has a distinct name in the logging, which can be a
globally constant name or ad-hoc, like the local __func__ string constant. Use
in the new struct msc_a, as well as change vlr_subscr to the new osmo_use_count
API.
* FSM Timeouts
Introduce using the new osmo_tdef API, which provides a common VTY
implementation for all timer numbers, and FSM state transitions with the
correct timeout. Originated in osmo-bsc, recently moved to libosmocore.
Depends: Ife31e6798b4e728a23913179e346552a7dd338c0 (libosmocore)
Ib9af67b100c4583342a2103669732dab2e577b04 (libosmocore)
Id617265337f09dfb6ddfe111ef5e578cd3dc9f63 (libosmocore)
Ie9e2add7bbfae651c04e230d62e37cebeb91b0f5 (libosmo-sccp)
I26be5c4b06a680f25f19797407ab56a5a4880ddc (osmo-mgw)
Ida0e59f9a1f2dd18efea0a51680a67b69f141efa (osmo-mgw)
I9a3effd38e72841529df6c135c077116981dea36 (osmo-mgw)
Change-Id: I27e4988e0371808b512c757d2b52ada1615067bd
|
|
Change-Id: I36929a4ba4abb46909181068d1d0af967b1f5a94
|
|
Depends: Ife31e6798b4e728a23913179e346552a7dd338c0 (libosmocore)
Change-Id: Ib06d030e8464abe415ff597d462ed40eeddef475
|
|
If the key_seq we get in the first messages matches the last_tuple, then
both we and the MS already know the key to use and we don't need the
AUTH REQUEST/RESPONSE cycle.
Security wise ... not so good, and so IMHO the 'auth required' option
in the MSC should always be set. But this allows to turn on ciphering on
a channel without doing any MM transaction, and so the MS doesn't turn
on the T3240 timer which allows to have a ciphered silent-call channel
that won't timeout.
Change-Id: Ief840a2ae7a0ffd2bf0bf726f209a79e3f787646
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
|
|
Add an SGs interface (3GPP TS 29.118) to osmo-msc in order to support
SMS tunneling and Circuit Switched Fallback (CSFB)
Change-Id: I73359925fc1ca72b33a1466e6ac41307f2f0b11d
Related: OS#3615
|
|
When check-imei-req is enabled in the VTY config, do not accept IMEIs
sent by the ME directly anymore. Send the IMEI to the EIR/HLR and wait
for its ACK or NACK.
OsmoHLR also accepts all IMEIs at this point, but this allows to
optionally store the IMEI in the HLR DB.
Depends: Ib240474b0c3c603ba840cf26babb38a44dfc9364 (osmo-hlr)
Related: OS#3733
Change-Id: Ife868ed71c36cdd02638072abebf61fc949080a7
|
|
Make the vsub argument of both vlr_subscr_msisdn_or_name()
and vlr_subscr_name() a const.
The LOGVSUBP() macro uses vlr_subscr_name() and will not generate a
warning anymore when used with a const vsub.
Change-Id: If609269191f4df6186d823a2eee14012846328e2
|
|
Replace locally defined enum ran_type with libosmocore's new enum
osmo_rat_type, and value_string ran_type_names with osmo_rat_type_names.
The string representations change, which has cosmetic effects on the test suite
expectations.
Depends: I659687aef7a4d67ca372a39fef31dee07aed7631 (libosmocore)
Change-Id: I2c78c265dc99df581e1b00e563d6912c7ffdb36b
|
|
In rare cases, a conn is already associated with a subscriber. So far, we
abort()ed on that, bringing the entire osmo-msc down. Rather log an error and
keep the service running.
In vlr.ops.subscr_assoc, add success/failure return value, and abort the
LU/PARQ on error.
I haven't figured out in detail yet why/how a subscriber would re-launch a
LU/PARQ on a conn that is already associated, so far it is merely clear that we
do not want to crash the MSC if that happens. A log is in OS#3742.
Related: OS#3742, OS#3743
Change-Id: Ic0d54644bc735700220b1ef3a4384c217d57d20f
|
|
Always use LAC which is part of Cell Global ID otherwise we might end up
in a situation where separately stored LAC differs.
Both are described in 3GPP TS 23.008 $2.4 as temporary subscriber data
to be stored in VLR. Both are defined in 3GPP TS 23.003. The LAC is part
of LAI which is part of CGI so there should be no case when those values
differ for a given subscriber.
Change-Id: I993ebc3e14f25e83124b6d3f8461a4b18f971f8e
|
|
Change-Id: I322072653b41cf250aa2c1e346e00bae884feb84
|
|
Add a 'ipa-name' VTY command which overrides the default IPA name
used by the MSC. This is a prerequisite for inter-MSC handover.
Related: OS#3355
Change-Id: I317d6c59f77e92fbb2b875a83dc0ec2fa5cb6006
|
|
gsm_subscriber.h contains some legacy cruft, part of which is that the VLR's
max MSISDN length should rather be defined in vlr.h. Same for GSM_NAME_LENGTH
-> VLR_NAME_LENGTH.
Adjust some sms_queue stuff that anyway includes vlr.h already.
Drop gsm_subscriber.h from vlr.h.
Add other (more concise) includes that thus become necessary, since the include
chain vlr.h->gsm_subscriber.h->gsm_data.h is no longer in place.
Change-Id: Iab5c507ec04fc2884187cf946f6ae2240e4a31f8
|
|
Along goes GSM_KEYSEQ_INVAL as VLR_*.
It's where it logically belongs, and is almost the only reason why vlr.h
includes gsm_data.h. The remaining reason, GSM_EXTENSION_LENGTH, will be moved
by upcoming patch.
Change-Id: I122feae7ee3cbc59e941daef35a954bce29fec76
|
|
With the dawn of inter-BSC,MSC handover, adopting the MSC-A,-I,-T roles from
3GPP TS 49.008, the RAN connection shall soon be a neatly separated corner of
osmo-msc, so gravitate ran_conn decarations to files of matching name.
Also, the current chaos of API defined in files with mismatching/meaningless
names drives me crazy.
Change-Id: Ice31e6c43e46678538c65261f150c67e1d0845e5
|
|
In preparation for inter-BSC and inter-MSC handover, we need to separate the
subscriber management logic from the actual RAN connections. What better time
to finally rename gsm_subscriber_connection.
* Name choice:
In 2G, this is a connection to the BSS, but even though 3GPP TS commonly talk
of "BSS-A" and "BSS-B" when explaining handover, it's not good to call it
"bss_conn": in 3G a BSS is called RNS, IIUC.
The overall term for 2G (GERAN) and 3G (UTRAN) is RAN: Radio Access Network.
* Rationale:
A subscriber in the MSC so far has only one RAN connection, but e.g. for
inter-BSC handover, a second one needs to be created to handover to. Most of
the items in the former gsm_subscriber_connection are actually related to the
RAN, with only a few MM and RTP related items. So, as a first step, just rename
it to ran_conn, to cosmetically prepare for moving the not strictly RAN related
items away later.
Also:
- Rename some functions from msc_subscr_conn_* to ran_conn_*
- Rename "Subscr_Conn" FSM instance name to "RAN_conn"
- Rename SUBSCR_CONN_* to RAN_CONN_*
Change-Id: Ic595f7a558d3553c067f77dc67543ab59659707a
|
|
Store all Classmark information in the VLR.
So, we now always know the Classmark 1 (mandatory IE for LU). This is visible
in the msc_vlr_tests -- they no longer indicate "assuming A5/1 is supported"
because classmark 1 is missing, because we now know the Classmark 1.
Rationale:
During Location Updating, we receive Classmark 1; during CM Service Request and
Paging Response, we receive Classmark 2. So far we stored these only for the
duration of the conn, so as soon as a LU is complete, we would forget CM1.
In other words, for anything else than a LU Request, we had no Classmark 1
available at all.
During Ciphering Mode Command, we rely on Classmark 1 to determine whether A5/1
is supported. That is moot if we don't even have a Classmark 1 for any CM
Service Request or Paging Response initiated connections.
The only reason that A5/1 worked is that we assume A5/1 to work if Classmark 1
is missing. To add to the confusion, if a phone indicated that it did *not*
support A5/1 in the Classmark 1, according to spec we're supposed to not
service it at all. A code comment however says that we instead want to heed the
flag -- which so far was only present in a Location Updating initiated
connection. Now we can make this decision without assuming things.
This got my attention while hacking on sending a BSSMAP Classmark Request from
the MSC if it finds missing Classmark information, and was surprised to see it
it lacking CM1 to decide about A5/1.
Change-Id: I27081bf6e9e017923b2d02607f7ea06beddad82a
|
|
The intention was to use the file's basename, but __BASE_FILE__ means "the root
file that is being parsed and contains #include statements".
If we had a function using __BASE_FILE__ and that was defined in an #included
file, __BASE_FILE__ would indicate the first file where the #include is, and
not the file where the function is defined. __BASE_FILE__ works for us because
we don't ever include function definitions that log something, so __BASE_FILE__
always coincides with __FILE__ for our logging; but still __BASE_FILE__ is
semantically the wrong constant.
Related: OS#2740
Change-Id: I1c8122c909938daaf782468c1c5b0262d555c3ce
|
|
osmo-hlr has recently (as of Change-Id
Iad227bb477d64da30dd6bfbbe1bd0c0a55be9474) a working shared library
implementation of libosmo-gsup-client.
We can remove the local implementation in osmo-msc and use the
system-installed shared library instead.
Change-Id: I6f542945403cf2e3ddac419186b09ec0e2d43b69
|
|
Some internal sub-systems, such as SS/USSD or SMS implementation,
may also need to use GSUP connection with HLR. Previously, it was
only available within the libvlr code, and nowhere else.
Let's introduce the generic GSUP message router, which will
receive messages unhandled by VLR itself, and route them to
a handler depending on the message type.
Change-Id: Ib8146ce5788c8f249dcaa39d61bd0388574bf892
|
|
Remove subscribers which fail to send periodic Location Updates from the
list of subscribers known to the VLR. This complements the IMSI detach
procedure: periodic LU expiry triggers an implicit IMSI detach.
Expired subscribers are purged from a periodic timer which iterates
over all subscribers once per minute.
Subscribers with an active connection do not expire. This is controlled
by the subscriber conn FSM which sets a subscriber's the LU expiry timeout
value to GSM_SUBSCRIBER_NO_EXPIRATION while a connection is active.
Add support for fake time with osmo_clock_gettime() to msc_vlr tests.
This functionality existed in OpenBSC but was lost during the nitb split.
This code took some inspiration from the OpenBSC implementation.
Related: OS#1976
Change-Id: Iebdee8b12d22acfcfb265ee41e71cfc8d9eb3ba9
|
|
Instead of keeping separate enums for FSM results and translating between those
and the actual 04.08 reject causes that will ultimately reach the MS, just pass
enum gsm48_reject_value cause codes around everywhere.
Collapse some VLR *_timeout() and *_cancel() api to just *_cancel() with a
gsm48 cause arg.
(Hopefully) improve a few reject causes, but otherwise just aim for more
transparent decisions on which cause value is used, for future fixes of
returned causes.
Depends: I6661f139e68a498fb1bef10c266c2f064b72774a (libosmocore)
Change-Id: I27bf8d68737ff1f8dc6d11fb1eac3d391aab0cb1
|
|
Since commit 2483f1b050496eda7f8707327204251c57212906 the function
gsm48_tx_mm_info() was not called anymore. No MM info messages were
transmitted to phones even if MM info messages were enabled via VTY.
With this commit, we call gsm48_tx_mm_info() after successfully
processing an IMSI ATTACH location update.
Change-Id: Ice5963d84253eb8c803cd2dfa8b25a4db5382827
Related: OS#2850
|
|
Define the struct vlr_ciph_result member .imeisv not as a char* but a char[] of
appropriate length, to avoid the need to point to external memory.
Thus fix a use-after-free in msc_cipher_mode_compl(), which defined the
imeisv[] buffer in a sub-scope within that function, so that the .imeisv
pointer was already invalid when fed to vlr_subscr_rx_ciph_res().
Did you notice that the commit summary rhymes?
Closes: OS#3053
Change-Id: I90cfb952a7dec6d104200872164ebadb25d0260d
|
|
Check and handle gracefully any error which might appear in
osmo_gsup_encode() - mark corresponding functions with
warn_unused_result attribute to make sure this failure is always checked
against.
Change-Id: I4551212011fb0bd898c020a183756ed7a9afb9e5
Related: OS#2864
|
|
The VLR code seems to have the assumption that there is one particular
algorithm to be used, as opposed to one of a set of algorithms.
What's missing is basically to decide when/where to pick the best
algorithm within the capabilities of the phone (classmark) and the
network configuration (net->a5_encryption_mask). So far, libvlr has no
notion of classmark. Rather, libmsc has.
Why does the VLR care about the particular algorithm at all? The VLR
should probably simply decide if it should use encryption or not, and if
so, the MSC will figure which algorithm to use.
Change-Id: I5ed80ca2086560a5975a758ec568a034a9a8ab89
|
|
Change-Id: If3852e096210713cb5297f6b42ed66dbb98c4a50
|
|
It's equivalent of existing vty command: common part is extracted into
shared helper function.
Change-Id: I267886b7c79ed6d9c2f34a2e60d2972b7f4f4036
|
|
* move log helpers to generic header
* log subscriber update
It's handy for troubleshooting issues with subscriber update via GSUP
from HLR.
Change-Id: I1958aeeb3ea99831c7e2c5ee9a6b59834baf4520
|
|
The expire_lu is never used but is printed for every subscriber. Let's
remove it to avoid confusion.
Change-Id: I6f7ad1670836384d1e6a58f47a13464fdbbf8509
|
|
Currently, if there is no reply from the BSS / RNC, a subscriber will remain as
"already paged" forever, and is never going to be paged again. Even on IMSI
Detach, the pending request will keep a ref count on the vlr_subscr.
Add a paging timeout, as gsm_network->paging_timeout and in the VTY on the
'msc' node as 'paging timeout (default|<1-65535>'. (There is a 'network' /
'T3113' in OsmoBSC, but to not confuse the two, give this a different name.)
Add test_ms_timeout_paging() test to verify the timeout works.
I hit this while testing Paging across multiple hNodeB, when a UE lost
connection to the hNodeB. I noticed that no matter how long I wait, no Paging
is sent out anymore, and found this embarrassing issue. Good grief...
The choice of 10 seconds is taken from https://osmocom.org/issues/2756
Change-Id: I2db6f1e2ad341cf9c2cc7a21ec2fca0bae5b2db5
|
|
In case of UMTS AKA, the Kc for ciphering must be derived from the 3G auth
tokens. tuple->vec.kc was calculated from the GSM algorithm and is not
necessarily a match for the UMTS AKA tokens.
To decide (in an upcoming patch) whether to use UMTS AKA derived Kc or the Kc
from the auth vector, the set_ciph_mode() from vlr_ops needs to know whether
UMTS AKA is being used. This could possibly derived from the msc_conn_ref, but
all flags are already available in the vlr_lu_fsm and vlr_access_req_fsm. Hence
add a umts_aka flag to the set_ciph_mode() callback invocation. The VLR FSMs
thus decide whether UMTS AKA or GSM AKA is to be used during Ciphering Mode
Command, which makes more sense than re-implementing the same decision process
in the MSC.
I considered placing the Kc derivation in vlr_set_ciph_mode() and only tell the
MSC's set_ciph_mode() implementation the precise keys it should use, but the
RAN particulars, and whether a Kc is used at all, rather belong with the MSC.
Related: OS#2745
Prepares: If04e405426c55a81341747a9b450a69188525d5c
Change-Id: I983c48347faf4ee1b405d8174b4e006c904157cf
|
|
During Set Ciphering Mode on GERAN, it is required to know whether UMTS AKA is
used to decide which Kc to pick. Change static function is_umts_auth() into
public vlr_use_umts_aka(), so future patches can re-use it.
Prepares: If04e405426c55a81341747a9b450a69188525d5c
Change-Id: I85d784c62ecbabdb6186a3dae4dcd554e7921041
|
|
The bit shifting is performed in gsm0808_enc_encrypt_info(), and must not be
done when populating the gsm0808_encrypt_info struct.
Provide vlr_ciph_to_gsm0808_alg_id() to translate the enum vlr_ciph to the
GSM0808_* constants we need to put in the gsm0808_encrypt_info struct instead.
Related: OS#2745
Change-Id: If75f95e8a5cc8b9979610ce6d746c1f0073ee39a
|
|
When sub_pres_vlr_fsm_start() is called, it dispatches an event which may in
some cases already cause tear down and free of the parent FSM instance, after
which storing the returned instance pointer in that parent's metadata will use
freed memory. Instead, pass the target pointer to remember the instance at to
sub_pres_vlr_fsm_start() and assign the pointer *before* firing the event.
Explain so in a new comment.
I haven't checked whether that pointer is actually used at all -- this is the
easiest way to fix the use-after-free without getting sucked into semantic
questions.
Change-Id: Ibdc0b64cd12ba3e2b9737e3517d8484e67abcf04
|
|
The name auth_tuple_max_use_count suggests that if I want to use each auth
tuple exactly once, I need to set it to 1. Curiously, so far you need to set
to intended uses - 1.
Reflect this in its name by renaming to auth_tuple_max_reuse_count.
I first considered to not rename but change the if-conditions so that == 1
means each tuple is used once, and upon struct vlr allocation, set the default
to 1. That would also logically entail that setting to 0 means to re-use
vectors infinitely often, like now a value < 0 does. That means, when
allocating a vlr struct zeroed out, we would by default have the most
dangerous/unsafe configuration. It's no problem to set a default to 1 upon
allocation, but by renaming the variable instead, we get safer alloc-zero
behavior and don't need to change any conditionals in the code (even though the
patch ends up considerably larger from all the renaming).
Change-Id: I0b036cae1536d5d6fb2304f837ed1a6c3713be55
|
|
Change-Id: I1f96a1285bbd1b4607614856bca935d5c26e2da9
|