aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom/msc/msc_roles.h
blob: b22bc7b85b314fec9201492ef87613596441b2c3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
#pragma once

#include <osmocom/core/fsm.h>
#include <osmocom/core/utils.h>
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/gsup.h>

#include <osmocom/msc/msc_common.h>
#include <osmocom/msc/ran_infra.h>

/* Each subscriber connection is managed by different roles, as described in 3GPP TS 49.008 '4.3 Roles of MSC-A, MSC-I
 * and MSC-T':
 *
 * MSC-A: subscriber management and control of all transactions (CC, SMS, USSD,...)
 * MSC-I: "internal": the actual BSSMAP link to the BSS, or RANAP link to the RNC.
 * MSC-T: "transitory": a new pending RAN link to a BSS or RNC, while handover is in progress.
 *        MSC-T becomes the new MSC-I once handover ends successfully.
 *
 * Without inter-MSC handover involved, all of the roles are managed by a single MSC instance.  During inter-MSC
 * handover negotiation, an MSC-T is set up at a remote MSC while MSC-A remains in the original MSC, and when handover
 * concludes successfully, the remote MSC-T becomes the new remote MSC-I, replacing the local MSC-I role.
 *
 * Furthermore, the 3GPP specs use the following terms for naming MSC locations: MSC-A, MSC-B and MSC-B', as well as BSS
 * or BSS-A, BSS-B and BSS-B':
 *
 * MSC-A: the first MSC the subscriber connected to.
 * MSC-B: a remote MSC (if any).
 * MSC-B': another remote MSC (if any, during Subsequent Handover).
 *
 * The full role assignments are spelled out in 3GPP TS 29.002.
 *
 * In Osmocom, the MAP protocol spoken between the MSCs is modeled using GSUP instead.
 *
 * Here are some diagrams of the lifecycle of a single subscriber's MSC-A,-I,-T roles at the locations MSC-A, MSC-B and
 * MSC-B'.
 *
 * Initially:
 *
 *             [MSC-A]
 *      BSS <-> MSC-I
 *
 * Then during inter-MSC handover negotiation:
 *
 *             [MSC-A] <-MAP-> MSC-B
 *      BSS <-> MSC-I          MSC-T <-> new BSS
 *
 * and when successful:
 *
 *             [MSC-A] <-MAP-> MSC-B
 *                             MSC-I <-> BSS
 *
 * Additional subsequent handover:
 *
 *             [MSC-A] <-MAP-> MSC-B
 *               ^             MSC-I <-> BSS
 *               |
 *               +-------MAP-> MSC-B'
 *                             MSC-T <-> new BSS
 *
 * (Here, quote, MSC-A "shall act as the target BSS towards the MSC-I and as the MSC towards the MSC-T.")
 * and when successful:
 *
 *             [MSC-A]
 *               ^
 *               |
 *               +-------MAP-> MSC-B 
 *                             MSC-I <-> BSS
 *
 * Subsequent handover back to the original MSC:
 *
 *             [MSC-A] <-MAP-> MSC-B
 *  new BSS <-> MSC-T          MSC-I <-> BSS
 *
 * and then
 *             [MSC-A]
 *      BSS <-> MSC-I
 *
 *
 * Inter-BSC Handover is just a special case of inter-MSC Handover, where the same MSC-A takes on both MSC-I and MSC-T
 * roles:
 *
 *             [MSC-A]
 *      BSS <-> MSC-I
 *  new BSS <-> MSC-T
 *
 * The mechanism to take on different roles is implemented by different FSM instances. Each FSM kind has one
 * implementation that acts locally, and another implementation to forward to a remote MSC. For example, in this
 * scenario:
 *
 *             [MSC-A] <-MAP-> MSC-B
 *                             MSC-I <-> BSS
 *
 * the implementation is
 *
 *     [MSC-A-----------------]            [MSC-B-----------------]
 *      msc_a <-> msc_i_REMOTE <---GSUP---> msc_a_REMOTE <-> msc_i <--BSSMAP--> [BSS]
 *
 * MSC-A has a locally acting msc_a FSM implementation. The msc_i FSM implementation at MSC-A receives signals from the
 * msc_a FSM and "merely" sends the MAP instructions to MSC-B.
 *
 * At MSC-B, in turn, the msc_a FSM's "remote" implementation receives the MAP messages and dispatches according events
 * to the MSC-B's local msc_i FSM instance, which is implemented to directly act towards the BSS.
 *
 * To implement single-MSC operation, we have the separate MSC roles' local implementations on the same MSC instance
 * instead of forwarding.
 *
 *
 * Use of MAP procedures on GSUP towards HLR:
 *
 * The MSC <-> VLR communication does still happen locally in the MSC-A only. In other words, there may be MAP message
 * handling between the MSCs (in the form of GSUP), but no MAP to talk to our internal VLR.
 *
 * From the VLR to the HLR, though, we again use GSUP for subscriber related HLR operations such as LU requesting and
 * retrieving auth tokens.
 *
 * To complete the picture, the MSC-A <--GSUP--> MSC-B forwarding happens over the same GSUP connection
 * as the VLR <--GSUP--> HLR link:
 *
 *    OsmoMSC
 *      MSC-A <----------E-interface--->+--GSUP--> [IPA routing] ----E--> MSC-B
 *       ^                              ^          (in osmo-hlr) \
 *       | (internal API)              /                          \--D--> HLR
 *       v                            /
 *      VLR <------------D-interface-/
 */

struct inter_msc_link;
struct ran_conn;

enum msc_role {
	MSC_ROLE_A,
	MSC_ROLE_I,
	MSC_ROLE_T,

	MSC_ROLES_COUNT
};

extern const struct value_string msc_role_names[];
static inline const char *msc_role_name(enum msc_role role)
{ return get_value_string(msc_role_names, role); }


enum msc_common_events {
	/* Explicitly start with 0 (first real event will be -1 + 1 = 0). */
	OFFSET_MSC_COMMON_EV = -1,

	MSC_REMOTE_EV_RX_GSUP,

	MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE,
	MSC_EV_CALL_LEG_RTP_COMPLETE,
	MSC_EV_CALL_LEG_TERM,

	/* MNCC has told us to RTP_CREATE, but local RTP port has not yet been set up.
	 * The MSC role should respond by calling mncc_set_rtp_stream() */
	MSC_MNCC_EV_NEED_LOCAL_RTP,
	MSC_MNCC_EV_CALL_PROCEEDING,
	MSC_MNCC_EV_CALL_COMPLETE,
	MSC_MNCC_EV_CALL_ENDED,

	LAST_MSC_COMMON_EV,
};


/* The events that the msc_a_local and msc_a_remote FSM implementations can receive,
 * according to specifications. Not all of these are necessarily implemented. */
enum msc_a_events {
	OFFSET_MSC_A_EV = LAST_MSC_COMMON_EV - 1,

	/* Establishing Layer 3 happens only at MSC-A (all-local MSC). To distinguish from the inter-MSC DTAP
	 * forwarding, keep this as a separate event. */
	MSC_A_EV_FROM_I_COMPLETE_LAYER_3,

	/* In inter-MSC situations, DTAP is forwarded transparently in AN-APDU IEs (formerly named
	 * BSS-APDU); see
	 * - 3GPP TS 49.008 4.2 'Transfer of DTAP and BSSMAP layer 3 messages on the * E-interface',
	 * - 3GPP TS 29.010 4.5.4 'BSSAP Messages transfer on E-Interface',
	 * - 3GPP TS 29.002 8.4.3 MAP_PROCESS_ACCESS_SIGNALLING service, 8.4.4 MAP_FORWARD_ACCESS_SIGNALLING service.
	 *
	 *   MSC-B ---DTAP--> MSC-A  MAP PROCESS ACCESS SIGNALLING request
	 *   MSC-B <--DTAP--- MSC-A  MAP FORWARD ACCESS SIGNALLING request
	 *   (where neither will receive a "response")
	 *
	 * See 3GPP TS 49.008 6. 'BSSMAP messages transferred on the E-interface'.
	 * Depending on the RAN, the AN-APDU contains a BSSMAP or a RANAP encoded message.
	 * MSC-I to MSC-A:
	 * - Managing attach to one BSC+MSC:
	 *   - CLASSMARK_UPDATE,
	 *   - CIPHER_MODE_COMPLETE,
	 *   - CIPHER_MODE_REJECT,
	 *   - ASSIGNMENT_COMPLETE,
	 *   - ASSIGNMENT_FAILURE,
	 *   - CLEAR_REQUEST,
	 * - Handover related messages:
	 *   - HANDOVER_REQUEST,
	 *   - HANDOVER_PERFORMED,
	 *   - HANDOVER_FAILURE,
	 * - Messages we don't need/support yet:
	 *   - CHANNEL_MODIFY_REQUEST (MSC assisted codec changing handover),
	 *   - SAPI_N_REJECT,
	 *   - CONFUSION,
	 *   - BSS_INVOKE_TRACE,
	 *   - QUEUING_INDICATION,
	 *   - PERFORM_LOCATION_REQUEST (*not* related to a Location Updating, but about passing the MS's geological
	 *     position)
	 *   - PERFORM_LOCATION_ABORT,
	 *   - PERFORM_LOCATION_RESPONSE,
	 *   - CONNECTION_ORIENTED_INFORMATION is listed in 48.008 3.2.1.70 as "(void)",
	 */
	MSC_A_EV_FROM_I_PROCESS_ACCESS_SIGNALLING_REQUEST,
	MSC_A_EV_FROM_I_PREPARE_SUBSEQUENT_HANDOVER_REQUEST,

	/* See 3GPP TS 29.002 8.4.2 MAP_SEND_END_SIGNAL service. */
	MSC_A_EV_FROM_I_SEND_END_SIGNAL_REQUEST,

	/* These BSSMAP messages are relevant for MSC-T -> MSC-A, i.e. from the transitory during inter-MSC handover:
	 *
	 * - Handover related messages:
	 *   - HANDOVER_REQUEST_ACKNOWLEDGE,
	 *   - HANDOVER_COMPLETE,
	 *   - HANDOVER_FAILURE,
	 *   - HANDOVER_DETECT,
	 *   - CLEAR_REQUEST,
	 * - Messages we don't need/support yet:
	 *   - CONFUSION,
	 *   - QUEUING_INDICATION,
	 */
	MSC_A_EV_FROM_T_PROCESS_ACCESS_SIGNALLING_REQUEST,

	/* Essentially the HO Request Ack. 3GPP TS 29.002 8.4.1 MAP_PREPARE_HANDOVER service. */
	MSC_A_EV_FROM_T_PREPARE_HANDOVER_RESPONSE,
	MSC_A_EV_FROM_T_PREPARE_HANDOVER_FAILURE,

	/* Done establishing the radio link to the MS, for Handover.
	 * See 3GPP TS 29.002 8.4.2 MAP_SEND_END_SIGNAL service.
	 * Not to be confused with the MSC_I_EV_FROM_A_SEND_END_SIGNAL_RESPONSE that tells MSC-B to release. */
	MSC_A_EV_FROM_T_SEND_END_SIGNAL_REQUEST,

	/* gsm_04_08.c has successfully received a valid Complete Layer 3 message, i.e. Location Updating, CM Service
	 * Request, Paging Reponse or IMSI Detach. */
	MSC_A_EV_COMPLETE_LAYER_3_OK,

	/* Received a Classmark Update -- during GERAN ciphering, msc_a may have to wait for Classmark information to
	 * determine supported ciphers. */
	MSC_A_EV_CLASSMARK_UPDATE,

	/* LU or Process Access FSM have determined that the peer has verified its authenticity. */
	MSC_A_EV_AUTHENTICATED,

	/* A valid request is starting to be processed on the connection. Upon this event, msc_a moves from
	 * MSC_A_ST_AUTHENTICATED to MSC_A_ST_COMMUNICATING, and enters the only state without an expiry timeout. */
	MSC_A_EV_TRANSACTION_ACCEPTED,

	/* MSC originated close request, e.g. all done, failed authentication, ... */
	MSC_A_EV_CN_CLOSE,

	/* Subscriber originated close request */
	MSC_A_EV_MO_CLOSE,

	/* msc_a->use_count has reached a total of zero. */
	MSC_A_EV_UNUSED,

	MSC_A_EV_HANDOVER_REQUIRED,
	MSC_A_EV_HANDOVER_END,

	/* indicates nr of MSC_A events, keep this as last enum value */
	LAST_MSC_A_EV
};
osmo_static_assert(LAST_MSC_A_EV <= 32, not_too_many_msc_a_events);

extern const struct value_string msc_a_fsm_event_names[];

enum msc_from_ran_events {
	OFFSET_MSC_EV_FROM_RAN = LAST_MSC_COMMON_EV - 1,

	MSC_EV_FROM_RAN_COMPLETE_LAYER_3,

	/* A BSSMAP/RANAP message came in on the RAN conn. */
	MSC_EV_FROM_RAN_UP_L2,

	/* The RAN connection is gone, or busy going. */
	MSC_EV_FROM_RAN_CONN_RELEASED,

	LAST_MSC_EV_FROM_RAN
};

/* The events that the msc_i_local and msc_i_remote FSM implementations can receive.
 * The MSC-I can also receive all msc_common_events and msc_from_ran_events. */
enum msc_i_events {
	OFFSET_E_MSC_I = LAST_MSC_EV_FROM_RAN - 1,

	/* BSSMAP/RANAP comes in from MSC-A to be sent out on the RAN conn.
	 * Depending on the RAN, the AN-APDU contains a BSSMAP or a RANAP encoded message.
	 * Relevant BSSMAP procedures, see 3GPP TS 49.008 6. 'BSSMAP messages transferred on the E-interface':
	 * - Managing attach to one BSC+MSC:
	 *   - CLASSMARK_REQUEST,
	 *   - CIPHER_MODE_COMMAND,
	 *   - COMMON_ID,
	 *   - ASSIGNMENT_REQUEST,
	 * - Handover related messages:
	 *   - HANDOVER_REQUEST_ACKNOWLEDGE,
	 *   - HANDOVER_FAILURE,
	 * - Messages we don't need/support yet:
	 *   - CONFUSION,
	 *   - MSC_INVOKE_TRACE,
	 *   - QUEUING_INDICATION,
	 *   - LSA_INFORMATION,
	 *   - PERFORM_LOCATION_REQUEST, (*not* related to a Location Updating, but about passing the MS's geological position)
	 *   - PERFORM_LOCATION_ABORT,
	 *   - PERFORM_LOCATION_RESPONSE,
	 *   - CONNECTION_ORIENTED_INFORMATION is listed in 48.008 3.2.1.70 as "(void)"
	 */
	MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST,

	/* MSC-A tells us to release the RAN connection. */
        MSC_I_EV_FROM_A_SEND_END_SIGNAL_RESPONSE,

	MSC_I_EV_FROM_A_PREPARE_SUBSEQUENT_HANDOVER_RESULT,
	MSC_I_EV_FROM_A_PREPARE_SUBSEQUENT_HANDOVER_ERROR,

	LAST_MSC_I_EV
};
osmo_static_assert(LAST_MSC_I_EV <= 32, not_too_many_msc_i_events);

extern const struct value_string msc_i_fsm_event_names[];

/* The events that the msc_t_local and msc_t_remote FSM implementations can receive.
 * The MSC-T can also receive all msc_common_events and msc_from_ran_events. */
enum msc_t_events {
	/* sufficient would be to use LAST_MSC_EV_FROM_RAN as offset. But while we have enough numbers
	 * available, it is a good idea to keep MSC-I and MSC-T events separate, to catch errors of
	 * sending wrong event kinds. */
        OFFSET_MSC_T_EV = LAST_MSC_I_EV - 1,

	/* BSSMAP/RANAP comes in from MSC-A to be sent out on the RAN conn.
	 * Relevant BSSMAP procedures, see 3GPP TS 49.008 6. 'BSSMAP messages transferred on the E-interface':
	 * - Handover related messages:
         *   - HANDOVER_REQUEST,
         *   - CLASSMARK_UPDATE, (?)
	 * - Messages we don't need/support yet:
	 *   - CONFUSION,
	 *   - MSC_INVOKE_TRACE,
	 *   - BSS_INVOKE_TRACE,
	 */
	MSC_T_EV_FROM_A_PREPARE_HANDOVER_REQUEST,
	MSC_T_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST,

	/* MSC originated close request, e.g. all done, failed handover, ... */
	MSC_T_EV_CN_CLOSE,

	/* Subscriber originated close request */
	MSC_T_EV_MO_CLOSE,

	MSC_T_EV_CLEAR_COMPLETE,

	LAST_MSC_T_EV
};
osmo_static_assert(LAST_MSC_T_EV <= 32, not_too_many_msc_t_events);

extern const struct value_string msc_t_fsm_event_names[];

/* All MSC role FSM implementations share this at the start of their fi->priv struct.
 * See struct msc_a, struct msc_i, struct msc_t in their individual headers. */
struct msc_role_common {
	enum msc_role role;

	struct osmo_fsm_inst *fi;

	/* For a local implementation, this is NULL. Otherwise, this identifies how to reach the remote
	 * MSC that this "remote" implementation forwards messages to. */
	struct e_link *remote_to;

	struct msub *msub;
	struct gsm_network *net;
	struct ran_infra *ran;
};

/* AccessNetworkSignalInfo as in 3GPP TS 29.002. */
struct an_apdu {
	/* accessNetworkProtocolId */
	enum osmo_gsup_access_network_protocol an_proto;
	/* signalInfo */
	struct msgb *msg;
	/* If this AN-APDU is sent between MSCs, additional information from the E-interface messaging, like the
	 * Handover Number, will placed/available here. Otherwise may be left NULL. */
	const struct osmo_gsup_message *e_info;
};