2016-06-16 22:06:42 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <osmocom/core/linuxlist.h>
|
|
|
|
#include <osmocom/core/fsm.h>
|
|
|
|
#include <osmocom/core/logging.h>
|
2019-02-19 01:36:35 +00:00
|
|
|
#include <osmocom/core/use_count.h>
|
2016-06-16 22:06:42 +00:00
|
|
|
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
|
|
|
#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
|
|
|
|
#include <osmocom/gsm/gsm23003.h>
|
2017-12-14 02:57:31 +00:00
|
|
|
#include <osmocom/gsm/gsm0808.h>
|
2018-06-13 20:54:33 +00:00
|
|
|
#include <osmocom/gsm/gsup.h>
|
2018-12-06 11:06:59 +00:00
|
|
|
#include <osmocom/gsm/ipa.h>
|
2018-11-29 23:44:32 +00:00
|
|
|
#include <osmocom/msc/ran_conn.h>
|
2018-11-30 01:46:53 +00:00
|
|
|
#include <osmocom/msc/msc_common.h>
|
2018-07-31 17:40:52 +00:00
|
|
|
#include <osmocom/gsupclient/gsup_client.h>
|
2018-12-03 10:00:04 +00:00
|
|
|
#include <osmocom/msc/vlr_sgs.h>
|
2016-06-16 22:06:42 +00:00
|
|
|
|
2017-12-27 12:23:44 +00:00
|
|
|
#define LOGGSUPP(level, gsup, fmt, args...) \
|
|
|
|
LOGP(DVLR, level, "GSUP(%s) " fmt, (gsup)->imsi, ## args)
|
|
|
|
|
|
|
|
#define LOGVSUBP(level, vsub, fmt, args...) \
|
|
|
|
LOGP(DVLR, level, "SUBSCR(%s) " fmt, vlr_subscr_name(vsub), ## args)
|
|
|
|
|
2016-06-19 16:06:02 +00:00
|
|
|
struct log_target;
|
|
|
|
|
2018-05-15 12:48:04 +00:00
|
|
|
#define VLR_SUBSCRIBER_NO_EXPIRATION 0
|
|
|
|
#define VLR_SUBSCRIBER_LU_EXPIRATION_INTERVAL 60 /* in seconds */
|
|
|
|
|
2019-02-19 01:36:35 +00:00
|
|
|
#define VSUB_USE_ATTACHED "attached"
|
|
|
|
|
2016-06-16 22:06:42 +00:00
|
|
|
/* from 3s to 10s */
|
|
|
|
#define GSM_29002_TIMER_S 10
|
|
|
|
/* from 15s to 30s */
|
|
|
|
#define GSM_29002_TIMER_M 30
|
|
|
|
/* from 1min to 10min */
|
|
|
|
#define GSM_29002_TIMER_ML (10*60)
|
|
|
|
/* from 28h to 38h */
|
|
|
|
#define GSM_29002_TIMER_L (32*60*60)
|
|
|
|
|
|
|
|
/* VLR subscriber authentication state */
|
|
|
|
enum vlr_subscr_auth_state {
|
|
|
|
/* subscriber needs to be autenticated */
|
|
|
|
VLR_SUB_AS_NEEDS_AUTH,
|
|
|
|
/* waiting for AuthInfo from HLR/AUC */
|
|
|
|
VLR_SUB_AS_NEEDS_AUTH_WAIT_AI,
|
|
|
|
/* waiting for response from subscriber */
|
|
|
|
VLR_SUB_AS_WAIT_RESP,
|
|
|
|
/* successfully authenticated */
|
|
|
|
VLR_SUB_AS_AUTHENTICATED,
|
|
|
|
/* subscriber needs re-sync */
|
|
|
|
VLR_SUB_AS_NEEDS_RESYNC,
|
|
|
|
/* waiting for AuthInfo with ReSync */
|
|
|
|
VLR_SUB_AS_NEEDS_AUTH_WAIT_SAI_RESYNC,
|
|
|
|
/* waiting for response from subscr, resync case */
|
|
|
|
VLR_SUB_AS_WAIT_RESP_RESYNC,
|
|
|
|
/* waiting for IMSI from subscriber */
|
|
|
|
VLR_SUB_AS_WAIT_ID_IMSI,
|
|
|
|
/* authentication has failed */
|
|
|
|
VLR_SUB_AS_AUTH_FAILED,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum vlr_lu_event {
|
|
|
|
VLR_ULA_E_UPDATE_LA, /* Initial trigger (LU from MS) */
|
|
|
|
VLR_ULA_E_SEND_ID_ACK, /* Result of Send-ID from PVLR */
|
|
|
|
VLR_ULA_E_SEND_ID_NACK, /* Result of Send-ID from PVLR */
|
|
|
|
VLR_ULA_E_AUTH_RES, /* Result of auth procedure */
|
|
|
|
VLR_ULA_E_CIPH_RES, /* Result of Ciphering Mode Command */
|
|
|
|
VLR_ULA_E_ID_IMSI, /* IMSI recieved from MS */
|
|
|
|
VLR_ULA_E_ID_IMEI, /* IMEI received from MS */
|
|
|
|
VLR_ULA_E_ID_IMEISV, /* IMEISV received from MS */
|
2018-12-14 16:37:38 +00:00
|
|
|
VLR_ULA_E_HLR_IMEI_ACK, /* Check_IMEI_VLR result from HLR */
|
|
|
|
VLR_ULA_E_HLR_IMEI_NACK,/* Check_IMEI_VLR result from HLR */
|
2016-06-16 22:06:42 +00:00
|
|
|
VLR_ULA_E_HLR_LU_RES, /* HLR UpdateLocation result */
|
|
|
|
VLR_ULA_E_UPD_HLR_COMPL,/* UpdatE_HLR_VLR result */
|
|
|
|
VLR_ULA_E_LU_COMPL_SUCCESS,/* Location_Update_Completion_VLR result */
|
|
|
|
VLR_ULA_E_LU_COMPL_FAILURE,/* Location_Update_Completion_VLR result */
|
|
|
|
VLR_ULA_E_NEW_TMSI_ACK, /* TMSI Reallocation Complete */
|
|
|
|
};
|
|
|
|
|
|
|
|
enum vlr_ciph_result_cause {
|
|
|
|
VLR_CIPH_REJECT, /* ? */
|
|
|
|
VLR_CIPH_COMPL,
|
|
|
|
};
|
|
|
|
|
2018-11-30 01:57:33 +00:00
|
|
|
struct vlr_auth_tuple {
|
|
|
|
int use_count;
|
|
|
|
int key_seq;
|
|
|
|
struct osmo_auth_vector vec;
|
|
|
|
};
|
|
|
|
#define VLR_KEY_SEQ_INVAL 7 /* GSM 04.08 - 10.5.1.2 */
|
|
|
|
|
|
|
|
|
2016-06-16 22:06:42 +00:00
|
|
|
enum vlr_subscr_security_context {
|
|
|
|
VLR_SEC_CTX_NONE,
|
|
|
|
VLR_SEC_CTX_GSM,
|
|
|
|
VLR_SEC_CTX_UMTS,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum vlr_lu_type {
|
|
|
|
VLR_LU_TYPE_PERIODIC,
|
|
|
|
VLR_LU_TYPE_IMSI_ATTACH,
|
|
|
|
VLR_LU_TYPE_REGULAR,
|
|
|
|
};
|
|
|
|
|
|
|
|
#define OSMO_LBUF_DECL(name, xlen) \
|
|
|
|
struct { \
|
|
|
|
uint8_t buf[xlen]; \
|
|
|
|
size_t len; \
|
|
|
|
} name
|
|
|
|
|
|
|
|
struct sgsn_mm_ctx;
|
|
|
|
struct vlr_instance;
|
|
|
|
|
2018-11-30 01:46:53 +00:00
|
|
|
#define VLR_NAME_LENGTH 160
|
|
|
|
|
2016-06-16 22:06:42 +00:00
|
|
|
/* The VLR subscriber is the part of the GSM subscriber state in VLR (CS) or
|
|
|
|
* SGSN (PS), particularly while interacting with the HLR via GSUP */
|
|
|
|
struct vlr_subscr {
|
|
|
|
struct llist_head list;
|
|
|
|
struct vlr_instance *vlr;
|
|
|
|
|
|
|
|
/* TODO either populate from HLR or drop this completely? */
|
|
|
|
long long unsigned int id;
|
|
|
|
|
|
|
|
/* Data from HLR */ /* 3GPP TS 23.008 */
|
|
|
|
/* Always use vlr_subscr_set_imsi() to write to imsi[] */
|
|
|
|
char imsi[GSM23003_IMSI_MAX_DIGITS+1]; /* 2.1.1.1 */
|
2019-05-25 12:27:17 +00:00
|
|
|
char msisdn[GSM23003_MSISDN_MAX_DIGITS+1]; /* 2.1.2 */
|
2018-11-30 01:46:53 +00:00
|
|
|
char name[VLR_NAME_LENGTH+1]; /* proprietary */
|
2016-06-16 22:06:42 +00:00
|
|
|
OSMO_LBUF_DECL(hlr, 16); /* 2.4.7 */
|
|
|
|
uint32_t periodic_lu_timer; /* 2.4.24 */
|
|
|
|
uint32_t age_indicator; /* 2.17.1 */
|
|
|
|
|
|
|
|
/* Authentication Data */
|
2018-11-30 01:57:33 +00:00
|
|
|
struct vlr_auth_tuple auth_tuples[5]; /* 2.3.1-2.3.4 */
|
|
|
|
struct vlr_auth_tuple *last_tuple;
|
2016-06-16 22:06:42 +00:00
|
|
|
enum vlr_subscr_security_context sec_ctx;
|
|
|
|
|
|
|
|
/* Data local to VLR is below */
|
|
|
|
uint32_t tmsi; /* 2.1.4 */
|
|
|
|
/* Newly allocated TMSI that was not yet acked by MS */
|
|
|
|
uint32_t tmsi_new;
|
|
|
|
|
|
|
|
struct osmo_cell_global_id cgi; /* 2.4.16 */
|
|
|
|
|
|
|
|
char imeisv[GSM23003_IMEISV_NUM_DIGITS+1]; /* 2.2.3 */
|
2019-05-02 11:39:26 +00:00
|
|
|
char imei[GSM23003_IMEI_NUM_DIGITS_NO_CHK+1]; /* 2.1.9 */
|
2016-06-16 22:06:42 +00:00
|
|
|
bool imsi_detached_flag; /* 2.7.1 */
|
|
|
|
bool conf_by_radio_contact_ind; /* 2.7.4.1 */
|
|
|
|
bool sub_dataconf_by_hlr_ind; /* 2.7.4.2 */
|
|
|
|
bool loc_conf_in_hlr_ind; /* 2.7.4.3 */
|
|
|
|
bool dormant_ind; /* 2.7.8 */
|
|
|
|
bool cancel_loc_rx; /* 2.7.8A */
|
|
|
|
bool ms_not_reachable_flag; /* 2.10.2 (MNRF) */
|
|
|
|
bool la_allowed;
|
|
|
|
|
2019-02-19 01:36:35 +00:00
|
|
|
struct osmo_use_count use_count;
|
large refactoring: support inter-BSC and inter-MSC Handover
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
2018-12-07 13:47:34 +00:00
|
|
|
struct osmo_use_count_entry use_count_buf[8];
|
|
|
|
int32_t max_total_use_count;
|
2016-06-16 22:06:42 +00:00
|
|
|
|
|
|
|
struct osmo_fsm_inst *lu_fsm;
|
|
|
|
struct osmo_fsm_inst *auth_fsm;
|
|
|
|
struct osmo_fsm_inst *proc_arq_fsm;
|
2018-12-03 10:00:04 +00:00
|
|
|
struct osmo_fsm_inst *sgs_fsm;
|
2016-06-16 22:06:42 +00:00
|
|
|
|
|
|
|
bool lu_complete;
|
2018-05-15 12:48:04 +00:00
|
|
|
time_t expire_lu;
|
2016-06-16 22:06:42 +00:00
|
|
|
|
|
|
|
void *msc_conn_ref;
|
|
|
|
|
|
|
|
/* PS (SGSN) specific parts */
|
|
|
|
struct {
|
|
|
|
struct llist_head pdp_list;
|
|
|
|
} ps;
|
|
|
|
/* CS (NITB/CSCN) specific parts */
|
|
|
|
struct {
|
|
|
|
/* pending requests */
|
|
|
|
bool is_paging;
|
fix paging: add timeout to discard unsuccessful paging
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
2017-12-15 02:02:27 +00:00
|
|
|
struct osmo_timer_list paging_response_timer;
|
2016-05-20 19:59:55 +00:00
|
|
|
/* list of struct subscr_request */
|
2016-06-16 22:06:42 +00:00
|
|
|
struct llist_head requests;
|
2016-05-20 19:59:55 +00:00
|
|
|
uint8_t lac;
|
2018-12-25 23:40:18 +00:00
|
|
|
enum osmo_rat_type attached_via_ran;
|
2016-06-16 22:06:42 +00:00
|
|
|
} cs;
|
2018-12-03 10:00:04 +00:00
|
|
|
/* SGs (MME) specific parts */
|
|
|
|
struct {
|
|
|
|
struct vlr_sgs_cfg cfg;
|
|
|
|
char mme_name[SGS_MME_NAME_LEN + 1];
|
|
|
|
struct osmo_location_area_id lai;
|
|
|
|
vlr_sgs_lu_response_cb_t response_cb;
|
|
|
|
vlr_sgs_lu_paging_cb_t paging_cb;
|
|
|
|
vlr_sgs_lu_mminfo_cb_t mminfo_cb;
|
|
|
|
enum sgsap_service_ind paging_serv_ind;
|
|
|
|
struct osmo_timer_list Ts5;
|
|
|
|
} sgs;
|
store classmark in vlr_subscr, not conn
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
2018-09-13 01:05:52 +00:00
|
|
|
|
large refactoring: support inter-BSC and inter-MSC Handover
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
2018-12-07 13:47:34 +00:00
|
|
|
struct osmo_gsm48_classmark classmark;
|
2016-06-16 22:06:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum vlr_ciph {
|
large refactoring: support inter-BSC and inter-MSC Handover
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
2018-12-07 13:47:34 +00:00
|
|
|
VLR_CIPH_NONE = 0, /*< A5/0, no encryption */
|
|
|
|
VLR_CIPH_A5_1 = 1, /*< A5/1, encryption */
|
|
|
|
VLR_CIPH_A5_2 = 2, /*< A5/2, deprecated export-grade encryption */
|
|
|
|
VLR_CIPH_A5_3 = 3, /*< A5/3, 'new secure' encryption */
|
2016-06-16 22:06:42 +00:00
|
|
|
};
|
|
|
|
|
2017-12-14 02:57:31 +00:00
|
|
|
static inline uint8_t vlr_ciph_to_gsm0808_alg_id(enum vlr_ciph ciph)
|
|
|
|
{
|
|
|
|
switch (ciph) {
|
|
|
|
case VLR_CIPH_NONE:
|
|
|
|
return GSM0808_ALG_ID_A5_0;
|
|
|
|
case VLR_CIPH_A5_1:
|
|
|
|
return GSM0808_ALG_ID_A5_1;
|
|
|
|
case VLR_CIPH_A5_2:
|
|
|
|
return GSM0808_ALG_ID_A5_2;
|
|
|
|
case VLR_CIPH_A5_3:
|
|
|
|
return GSM0808_ALG_ID_A5_3;
|
large refactoring: support inter-BSC and inter-MSC Handover
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
2018-12-07 13:47:34 +00:00
|
|
|
default:
|
|
|
|
return GSM0808_ALG_ID_A5_7;
|
2017-12-14 02:57:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-16 22:06:42 +00:00
|
|
|
struct vlr_ops {
|
|
|
|
/* encode + transmit an AUTH REQ towards the MS.
|
|
|
|
* \param[in] at auth tuple providing rand, key_seq and autn.
|
|
|
|
* \param[in] send_autn True to send AUTN, for r99 UMTS auth.
|
|
|
|
*/
|
2018-11-30 01:57:33 +00:00
|
|
|
int (*tx_auth_req)(void *msc_conn_ref, struct vlr_auth_tuple *at,
|
2016-06-16 22:06:42 +00:00
|
|
|
bool send_autn);
|
|
|
|
/* encode + transmit an AUTH REJECT towards the MS */
|
|
|
|
int (*tx_auth_rej)(void *msc_conn_ref);
|
|
|
|
|
|
|
|
/* encode + transmit an IDENTITY REQUEST towards the MS */
|
|
|
|
int (*tx_id_req)(void *msc_conn_ref, uint8_t mi_type);
|
|
|
|
|
|
|
|
int (*tx_lu_acc)(void *msc_conn_ref, uint32_t send_tmsi);
|
2018-04-06 00:57:51 +00:00
|
|
|
int (*tx_lu_rej)(void *msc_conn_ref, enum gsm48_reject_value cause);
|
large refactoring: support inter-BSC and inter-MSC Handover
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
2018-12-07 13:47:34 +00:00
|
|
|
int (*tx_cm_serv_acc)(void *msc_conn_ref, enum osmo_cm_service_type cm_service_type);
|
|
|
|
int (*tx_cm_serv_rej)(void *msc_conn_ref, enum osmo_cm_service_type cm_service_type,
|
|
|
|
enum gsm48_reject_value cause);
|
2016-06-16 22:06:42 +00:00
|
|
|
|
2017-12-23 17:51:48 +00:00
|
|
|
int (*set_ciph_mode)(void *msc_conn_ref, bool umts_aka, bool retrieve_imeisv);
|
2016-06-16 22:06:42 +00:00
|
|
|
|
2016-05-20 19:59:55 +00:00
|
|
|
int (*tx_common_id)(void *msc_conn_ref);
|
|
|
|
|
2018-03-13 20:11:49 +00:00
|
|
|
int (*tx_mm_info)(void *msc_conn_ref);
|
2016-05-20 19:59:55 +00:00
|
|
|
|
2016-06-16 22:06:42 +00:00
|
|
|
/* notify MSC/SGSN that the subscriber data in VLR has been updated */
|
|
|
|
void (*subscr_update)(struct vlr_subscr *vsub);
|
|
|
|
/* notify MSC/SGSN that the given subscriber has been associated
|
|
|
|
* with this msc_conn_ref */
|
2018-12-28 20:22:32 +00:00
|
|
|
int (*subscr_assoc)(void *msc_conn_ref, struct vlr_subscr *vsub);
|
2016-06-16 22:06:42 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
enum vlr_timer {
|
|
|
|
VLR_T_3250,
|
|
|
|
VLR_T_3260,
|
|
|
|
VLR_T_3270,
|
|
|
|
_NUM_VLR_TIMERS
|
|
|
|
};
|
|
|
|
|
|
|
|
/* An instance of the VLR codebase */
|
|
|
|
struct vlr_instance {
|
|
|
|
struct llist_head subscribers;
|
|
|
|
struct llist_head operations;
|
large refactoring: support inter-BSC and inter-MSC Handover
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
2018-12-07 13:47:34 +00:00
|
|
|
struct gsup_client_mux *gcm;
|
2016-06-16 22:06:42 +00:00
|
|
|
struct vlr_ops ops;
|
2018-05-15 12:48:04 +00:00
|
|
|
struct osmo_timer_list lu_expire_timer;
|
2016-06-16 22:06:42 +00:00
|
|
|
struct {
|
2017-07-18 13:39:27 +00:00
|
|
|
bool retrieve_imeisv_early;
|
|
|
|
bool retrieve_imeisv_ciphered;
|
2016-06-16 22:06:42 +00:00
|
|
|
bool assign_tmsi;
|
|
|
|
bool check_imei_rqd;
|
2017-10-29 01:11:18 +00:00
|
|
|
int auth_tuple_max_reuse_count;
|
2016-06-16 22:06:42 +00:00
|
|
|
bool auth_reuse_old_sets_on_error;
|
|
|
|
bool parq_retrieve_imsi;
|
|
|
|
bool is_ps;
|
|
|
|
uint32_t timer[_NUM_VLR_TIMERS];
|
|
|
|
} cfg;
|
|
|
|
/* A free-form pointer for use by the caller */
|
|
|
|
void *user_ctx;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern const struct value_string vlr_ciph_names[];
|
|
|
|
static inline const char *vlr_ciph_name(enum vlr_ciph val)
|
|
|
|
{
|
|
|
|
return get_value_string(vlr_ciph_names, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Location Updating request */
|
|
|
|
struct osmo_fsm_inst *
|
|
|
|
vlr_loc_update(struct osmo_fsm_inst *parent,
|
|
|
|
uint32_t parent_event_success,
|
|
|
|
uint32_t parent_event_failure,
|
|
|
|
void *parent_event_data,
|
|
|
|
struct vlr_instance *vlr, void *msc_conn_ref,
|
|
|
|
enum vlr_lu_type type, uint32_t tmsi, const char *imsi,
|
|
|
|
const struct osmo_location_area_id *old_lai,
|
|
|
|
const struct osmo_location_area_id *new_lai,
|
|
|
|
bool authentication_required,
|
2017-12-23 17:51:48 +00:00
|
|
|
bool ciphering_required,
|
2019-03-14 10:02:36 +00:00
|
|
|
uint8_t key_seq,
|
2016-06-16 22:06:42 +00:00
|
|
|
bool is_r99, bool is_utran,
|
|
|
|
bool assign_tmsi);
|
|
|
|
|
2018-04-06 00:57:51 +00:00
|
|
|
void vlr_loc_update_cancel(struct osmo_fsm_inst *fi,
|
|
|
|
enum osmo_fsm_term_cause fsm_cause,
|
|
|
|
uint8_t gsm48_cause);
|
2016-06-16 22:06:42 +00:00
|
|
|
|
rename gsm_subscriber_connection to ran_conn
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
2018-11-29 21:37:51 +00:00
|
|
|
/* tell the VLR that the RAN connection is gone */
|
2016-06-16 22:06:42 +00:00
|
|
|
int vlr_subscr_disconnected(struct vlr_subscr *vsub);
|
2017-12-27 18:34:15 +00:00
|
|
|
bool vlr_subscr_expire(struct vlr_subscr *vsub);
|
2016-06-16 22:06:42 +00:00
|
|
|
int vlr_subscr_rx_id_resp(struct vlr_subscr *vsub, const uint8_t *mi, size_t mi_len);
|
|
|
|
int vlr_subscr_rx_auth_resp(struct vlr_subscr *vsub, bool is_r99, bool is_utran,
|
|
|
|
const uint8_t *res, uint8_t res_len);
|
|
|
|
int vlr_subscr_rx_auth_fail(struct vlr_subscr *vsub, const uint8_t *auts);
|
2018-01-24 11:48:33 +00:00
|
|
|
int vlr_subscr_tx_auth_fail_rep(const struct vlr_subscr *vsub) __attribute__((warn_unused_result));
|
large refactoring: support inter-BSC and inter-MSC Handover
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
2018-12-07 13:47:34 +00:00
|
|
|
void vlr_subscr_rx_ciph_res(struct vlr_subscr *vsub, enum vlr_ciph_result_cause result);
|
2016-06-16 22:06:42 +00:00
|
|
|
int vlr_subscr_rx_tmsi_reall_compl(struct vlr_subscr *vsub);
|
|
|
|
int vlr_subscr_rx_imsi_detach(struct vlr_subscr *vsub);
|
|
|
|
|
|
|
|
struct vlr_instance *vlr_alloc(void *ctx, const struct vlr_ops *ops);
|
large refactoring: support inter-BSC and inter-MSC Handover
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
2018-12-07 13:47:34 +00:00
|
|
|
int vlr_start(struct vlr_instance *vlr, struct gsup_client_mux *gcm);
|
|
|
|
int vlr_gsup_rx(struct gsup_client_mux *gcm, void *data, const struct osmo_gsup_message *gsup_msg);
|
2016-06-16 22:06:42 +00:00
|
|
|
|
|
|
|
/* internal use only */
|
|
|
|
|
2017-11-18 21:19:55 +00:00
|
|
|
void sub_pres_vlr_fsm_start(struct osmo_fsm_inst **fsm,
|
|
|
|
struct osmo_fsm_inst *parent,
|
|
|
|
struct vlr_subscr *vsub,
|
|
|
|
uint32_t term_event);
|
2016-06-16 22:06:42 +00:00
|
|
|
struct osmo_fsm_inst *
|
|
|
|
upd_hlr_vlr_proc_start(struct osmo_fsm_inst *parent,
|
|
|
|
struct vlr_subscr *vsub,
|
|
|
|
uint32_t parent_event);
|
|
|
|
|
|
|
|
struct osmo_fsm_inst *
|
|
|
|
lu_compl_vlr_proc_start(struct osmo_fsm_inst *parent,
|
|
|
|
struct vlr_subscr *vsub,
|
|
|
|
void *msc_conn_ref,
|
|
|
|
uint32_t parent_event_success,
|
|
|
|
uint32_t parent_event_failure);
|
|
|
|
|
|
|
|
|
2019-01-08 10:47:21 +00:00
|
|
|
const char *vlr_subscr_name(const struct vlr_subscr *vsub);
|
large refactoring: support inter-BSC and inter-MSC Handover
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
2018-12-07 13:47:34 +00:00
|
|
|
const char *vlr_subscr_short_name(const struct vlr_subscr *vsub, unsigned int maxlen);
|
2019-01-08 10:47:21 +00:00
|
|
|
const char *vlr_subscr_msisdn_or_name(const struct vlr_subscr *vsub);
|
2016-06-16 22:06:42 +00:00
|
|
|
|
2019-02-19 01:36:35 +00:00
|
|
|
#define vlr_subscr_find_by_imsi(vlr, imsi, USE) \
|
|
|
|
_vlr_subscr_find_by_imsi(vlr, imsi, USE, __FILE__, __LINE__)
|
|
|
|
#define vlr_subscr_find_or_create_by_imsi(vlr, imsi, USE, created) \
|
|
|
|
_vlr_subscr_find_or_create_by_imsi(vlr, imsi, USE, created, \
|
2018-08-20 10:41:36 +00:00
|
|
|
__FILE__, __LINE__)
|
2016-06-16 22:06:42 +00:00
|
|
|
|
2019-02-19 01:36:35 +00:00
|
|
|
#define vlr_subscr_find_by_tmsi(vlr, tmsi, USE) \
|
|
|
|
_vlr_subscr_find_by_tmsi(vlr, tmsi, USE, __FILE__, __LINE__)
|
|
|
|
#define vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, USE, created) \
|
|
|
|
_vlr_subscr_find_or_create_by_tmsi(vlr, tmsi, USE, created, \
|
2018-08-20 10:41:36 +00:00
|
|
|
__FILE__, __LINE__)
|
2016-06-16 22:06:42 +00:00
|
|
|
|
2019-02-19 01:36:35 +00:00
|
|
|
#define vlr_subscr_find_by_msisdn(vlr, msisdn, USE) \
|
|
|
|
_vlr_subscr_find_by_msisdn(vlr, msisdn, USE, __FILE__, __LINE__)
|
2016-06-16 22:06:42 +00:00
|
|
|
|
|
|
|
struct vlr_subscr *_vlr_subscr_find_by_imsi(struct vlr_instance *vlr,
|
|
|
|
const char *imsi,
|
2019-02-19 01:36:35 +00:00
|
|
|
const char *use,
|
2016-06-16 22:06:42 +00:00
|
|
|
const char *file, int line);
|
|
|
|
struct vlr_subscr *_vlr_subscr_find_or_create_by_imsi(struct vlr_instance *vlr,
|
|
|
|
const char *imsi,
|
2019-02-19 01:36:35 +00:00
|
|
|
const char *use,
|
2016-06-16 22:06:42 +00:00
|
|
|
bool *created,
|
|
|
|
const char *file,
|
|
|
|
int line);
|
|
|
|
|
|
|
|
struct vlr_subscr *_vlr_subscr_find_by_tmsi(struct vlr_instance *vlr,
|
|
|
|
uint32_t tmsi,
|
2019-02-19 01:36:35 +00:00
|
|
|
const char *use,
|
2016-06-16 22:06:42 +00:00
|
|
|
const char *file, int line);
|
|
|
|
struct vlr_subscr *_vlr_subscr_find_or_create_by_tmsi(struct vlr_instance *vlr,
|
|
|
|
uint32_t tmsi,
|
2019-02-19 01:36:35 +00:00
|
|
|
const char *use,
|
2016-06-16 22:06:42 +00:00
|
|
|
bool *created,
|
|
|
|
const char *file,
|
|
|
|
int line);
|
|
|
|
|
|
|
|
struct vlr_subscr *_vlr_subscr_find_by_msisdn(struct vlr_instance *vlr,
|
|
|
|
const char *msisdn,
|
2019-02-19 01:36:35 +00:00
|
|
|
const char *use,
|
2016-06-16 22:06:42 +00:00
|
|
|
const char *file, int line);
|
|
|
|
|
2019-02-19 01:36:35 +00:00
|
|
|
#define vlr_subscr_get(VSUB, USE) vlr_subscr_get_src(VSUB, USE, __FILE__, __LINE__)
|
|
|
|
#define vlr_subscr_put(VSUB, USE) vlr_subscr_put_src(VSUB, USE, __FILE__, __LINE__)
|
|
|
|
|
|
|
|
#define vlr_subscr_get_src(VSUB, USE, SRCFILE, SRCLINE) \
|
2019-04-23 13:09:04 +00:00
|
|
|
OSMO_ASSERT((VSUB) && _osmo_use_count_get_put(&(VSUB)->use_count, USE, 1, SRCFILE, SRCLINE) == 0)
|
2019-02-19 01:36:35 +00:00
|
|
|
#define vlr_subscr_put_src(VSUB, USE, SRCFILE, SRCLINE) \
|
2019-04-23 13:09:04 +00:00
|
|
|
OSMO_ASSERT((VSUB) && _osmo_use_count_get_put(&(VSUB)->use_count, USE, -1, SRCFILE, SRCLINE) == 0)
|
2016-06-16 22:06:42 +00:00
|
|
|
|
|
|
|
void vlr_subscr_free(struct vlr_subscr *vsub);
|
|
|
|
int vlr_subscr_alloc_tmsi(struct vlr_subscr *vsub);
|
|
|
|
|
|
|
|
void vlr_subscr_set_imsi(struct vlr_subscr *vsub, const char *imsi);
|
|
|
|
void vlr_subscr_set_imei(struct vlr_subscr *vsub, const char *imei);
|
|
|
|
void vlr_subscr_set_imeisv(struct vlr_subscr *vsub, const char *imeisv);
|
|
|
|
void vlr_subscr_set_msisdn(struct vlr_subscr *vsub, const char *msisdn);
|
|
|
|
|
|
|
|
bool vlr_subscr_matches_imsi(struct vlr_subscr *vsub, const char *imsi);
|
|
|
|
bool vlr_subscr_matches_tmsi(struct vlr_subscr *vsub, uint32_t tmsi);
|
|
|
|
bool vlr_subscr_matches_msisdn(struct vlr_subscr *vsub, const char *msisdn);
|
|
|
|
bool vlr_subscr_matches_imei(struct vlr_subscr *vsub, const char *imei);
|
|
|
|
|
|
|
|
uint32_t vlr_timer(struct vlr_instance *vlr, uint32_t timer);
|
|
|
|
|
|
|
|
int vlr_subscr_changed(struct vlr_subscr *vsub);
|
2018-01-24 11:48:33 +00:00
|
|
|
int vlr_subscr_purge(struct vlr_subscr *vsub) __attribute__((warn_unused_result));
|
2018-04-06 00:57:51 +00:00
|
|
|
void vlr_subscr_cancel_attach_fsm(struct vlr_subscr *vsub,
|
|
|
|
enum osmo_fsm_term_cause fsm_cause,
|
|
|
|
uint8_t gsm48_cause);
|
2016-06-16 22:06:42 +00:00
|
|
|
|
2018-05-15 12:48:04 +00:00
|
|
|
void vlr_subscr_enable_expire_lu(struct vlr_subscr *vsub);
|
2016-06-16 22:06:42 +00:00
|
|
|
|
|
|
|
/* Process Acccess Request FSM */
|
|
|
|
|
|
|
|
enum proc_arq_vlr_event {
|
|
|
|
PR_ARQ_E_START,
|
|
|
|
PR_ARQ_E_ID_IMSI,
|
|
|
|
PR_ARQ_E_AUTH_RES,
|
|
|
|
PR_ARQ_E_CIPH_RES,
|
|
|
|
PR_ARQ_E_UPD_LOC_RES,
|
|
|
|
PR_ARQ_E_TRACE_RES,
|
|
|
|
PR_ARQ_E_IMEI_RES,
|
|
|
|
PR_ARQ_E_PRES_RES,
|
|
|
|
PR_ARQ_E_TMSI_ACK,
|
|
|
|
};
|
|
|
|
|
|
|
|
enum vlr_parq_type {
|
|
|
|
VLR_PR_ARQ_T_INVALID = 0, /* to guard against unset vars */
|
|
|
|
VLR_PR_ARQ_T_CM_SERV_REQ,
|
|
|
|
VLR_PR_ARQ_T_PAGING_RESP,
|
|
|
|
/* FIXME: differentiate between services of 24.008 10.5.3.3 */
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Process Access Request (CM SERV REQ / PAGING RESP) */
|
|
|
|
void
|
|
|
|
vlr_proc_acc_req(struct osmo_fsm_inst *parent,
|
|
|
|
uint32_t parent_event_success,
|
|
|
|
uint32_t parent_event_failure,
|
|
|
|
void *parent_event_data,
|
|
|
|
struct vlr_instance *vlr, void *msc_conn_ref,
|
large refactoring: support inter-BSC and inter-MSC Handover
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
2018-12-07 13:47:34 +00:00
|
|
|
enum vlr_parq_type type, enum osmo_cm_service_type cm_service_type,
|
|
|
|
const uint8_t *mi_lv,
|
2016-06-16 22:06:42 +00:00
|
|
|
const struct osmo_location_area_id *lai,
|
|
|
|
bool authentication_required,
|
2017-12-23 17:51:48 +00:00
|
|
|
bool ciphering_required,
|
2019-03-14 10:02:36 +00:00
|
|
|
uint8_t key_seq,
|
2016-06-16 22:06:42 +00:00
|
|
|
bool is_r99, bool is_utran);
|
|
|
|
|
2018-04-06 00:57:51 +00:00
|
|
|
void vlr_parq_cancel(struct osmo_fsm_inst *fi,
|
|
|
|
enum osmo_fsm_term_cause fsm_cause,
|
|
|
|
enum gsm48_reject_value gsm48_cause);
|
2016-06-16 22:06:42 +00:00
|
|
|
|
|
|
|
void vlr_parq_fsm_init(void);
|
|
|
|
|
|
|
|
int vlr_set_ciph_mode(struct vlr_instance *vlr,
|
|
|
|
struct osmo_fsm_inst *fi,
|
|
|
|
void *msc_conn_ref,
|
2017-12-23 17:51:48 +00:00
|
|
|
bool ciph_required,
|
2017-12-18 00:23:42 +00:00
|
|
|
bool umts_aka,
|
2016-06-16 22:06:42 +00:00
|
|
|
bool retrieve_imeisv);
|
|
|
|
|
2017-12-18 01:06:44 +00:00
|
|
|
bool vlr_use_umts_aka(struct osmo_auth_vector *vec, bool is_r99);
|
|
|
|
|
2016-06-16 22:06:42 +00:00
|
|
|
void log_set_filter_vlr_subscr(struct log_target *target,
|
|
|
|
struct vlr_subscr *vlr_subscr);
|
2019-08-19 13:30:12 +00:00
|
|
|
|
|
|
|
void vlr_gmm_cause_to_mm_cause(enum gsm48_gmm_cause gmm_cause,
|
|
|
|
enum gsm48_reject_value *gsm48_rej_p);
|