Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 1 | #pragma once |
| 2 | |
| 3 | #include <osmocom/core/fsm.h> |
| 4 | #include <osmocom/core/utils.h> |
| 5 | #include <osmocom/gsm/gsm_utils.h> |
| 6 | #include <osmocom/gsm/gsup.h> |
| 7 | |
| 8 | #include <osmocom/msc/msc_common.h> |
| 9 | #include <osmocom/msc/ran_infra.h> |
| 10 | |
| 11 | /* Each subscriber connection is managed by different roles, as described in 3GPP TS 49.008 '4.3 Roles of MSC-A, MSC-I |
| 12 | * and MSC-T': |
| 13 | * |
| 14 | * MSC-A: subscriber management and control of all transactions (CC, SMS, USSD,...) |
| 15 | * MSC-I: "internal": the actual BSSMAP link to the BSS, or RANAP link to the RNC. |
| 16 | * MSC-T: "transitory": a new pending RAN link to a BSS or RNC, while handover is in progress. |
| 17 | * MSC-T becomes the new MSC-I once handover ends successfully. |
| 18 | * |
| 19 | * Without inter-MSC handover involved, all of the roles are managed by a single MSC instance. During inter-MSC |
| 20 | * handover negotiation, an MSC-T is set up at a remote MSC while MSC-A remains in the original MSC, and when handover |
| 21 | * concludes successfully, the remote MSC-T becomes the new remote MSC-I, replacing the local MSC-I role. |
| 22 | * |
| 23 | * Furthermore, the 3GPP specs use the following terms for naming MSC locations: MSC-A, MSC-B and MSC-B', as well as BSS |
| 24 | * or BSS-A, BSS-B and BSS-B': |
| 25 | * |
| 26 | * MSC-A: the first MSC the subscriber connected to. |
| 27 | * MSC-B: a remote MSC (if any). |
| 28 | * MSC-B': another remote MSC (if any, during Subsequent Handover). |
| 29 | * |
| 30 | * The full role assignments are spelled out in 3GPP TS 29.002. |
| 31 | * |
| 32 | * In Osmocom, the MAP protocol spoken between the MSCs is modeled using GSUP instead. |
| 33 | * |
| 34 | * 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 |
| 35 | * MSC-B'. |
| 36 | * |
| 37 | * Initially: |
| 38 | * |
| 39 | * [MSC-A] |
| 40 | * BSS <-> MSC-I |
| 41 | * |
| 42 | * Then during inter-MSC handover negotiation: |
| 43 | * |
| 44 | * [MSC-A] <-MAP-> MSC-B |
| 45 | * BSS <-> MSC-I MSC-T <-> new BSS |
| 46 | * |
| 47 | * and when successful: |
| 48 | * |
| 49 | * [MSC-A] <-MAP-> MSC-B |
| 50 | * MSC-I <-> BSS |
| 51 | * |
| 52 | * Additional subsequent handover: |
| 53 | * |
| 54 | * [MSC-A] <-MAP-> MSC-B |
| 55 | * ^ MSC-I <-> BSS |
| 56 | * | |
| 57 | * +-------MAP-> MSC-B' |
| 58 | * MSC-T <-> new BSS |
| 59 | * |
| 60 | * (Here, quote, MSC-A "shall act as the target BSS towards the MSC-I and as the MSC towards the MSC-T.") |
| 61 | * and when successful: |
| 62 | * |
| 63 | * [MSC-A] |
| 64 | * ^ |
| 65 | * | |
| 66 | * +-------MAP-> MSC-B |
| 67 | * MSC-I <-> BSS |
| 68 | * |
| 69 | * Subsequent handover back to the original MSC: |
| 70 | * |
| 71 | * [MSC-A] <-MAP-> MSC-B |
| 72 | * new BSS <-> MSC-T MSC-I <-> BSS |
| 73 | * |
| 74 | * and then |
| 75 | * [MSC-A] |
| 76 | * BSS <-> MSC-I |
| 77 | * |
| 78 | * |
| 79 | * 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 |
| 80 | * roles: |
| 81 | * |
| 82 | * [MSC-A] |
| 83 | * BSS <-> MSC-I |
| 84 | * new BSS <-> MSC-T |
| 85 | * |
| 86 | * The mechanism to take on different roles is implemented by different FSM instances. Each FSM kind has one |
| 87 | * implementation that acts locally, and another implementation to forward to a remote MSC. For example, in this |
| 88 | * scenario: |
| 89 | * |
| 90 | * [MSC-A] <-MAP-> MSC-B |
| 91 | * MSC-I <-> BSS |
| 92 | * |
| 93 | * the implementation is |
| 94 | * |
| 95 | * [MSC-A-----------------] [MSC-B-----------------] |
| 96 | * msc_a <-> msc_i_REMOTE <---GSUP---> msc_a_REMOTE <-> msc_i <--BSSMAP--> [BSS] |
| 97 | * |
| 98 | * MSC-A has a locally acting msc_a FSM implementation. The msc_i FSM implementation at MSC-A receives signals from the |
| 99 | * msc_a FSM and "merely" sends the MAP instructions to MSC-B. |
| 100 | * |
| 101 | * At MSC-B, in turn, the msc_a FSM's "remote" implementation receives the MAP messages and dispatches according events |
| 102 | * to the MSC-B's local msc_i FSM instance, which is implemented to directly act towards the BSS. |
| 103 | * |
| 104 | * To implement single-MSC operation, we have the separate MSC roles' local implementations on the same MSC instance |
| 105 | * instead of forwarding. |
| 106 | * |
| 107 | * |
| 108 | * Use of MAP procedures on GSUP towards HLR: |
| 109 | * |
| 110 | * The MSC <-> VLR communication does still happen locally in the MSC-A only. In other words, there may be MAP message |
| 111 | * handling between the MSCs (in the form of GSUP), but no MAP to talk to our internal VLR. |
| 112 | * |
| 113 | * From the VLR to the HLR, though, we again use GSUP for subscriber related HLR operations such as LU requesting and |
| 114 | * retrieving auth tokens. |
| 115 | * |
| 116 | * To complete the picture, the MSC-A <--GSUP--> MSC-B forwarding happens over the same GSUP connection |
| 117 | * as the VLR <--GSUP--> HLR link: |
| 118 | * |
| 119 | * OsmoMSC |
| 120 | * MSC-A <----------E-interface--->+--GSUP--> [IPA routing] ----E--> MSC-B |
| 121 | * ^ ^ (in osmo-hlr) \ |
| 122 | * | (internal API) / \--D--> HLR |
| 123 | * v / |
| 124 | * VLR <------------D-interface-/ |
| 125 | */ |
| 126 | |
| 127 | struct inter_msc_link; |
| 128 | struct ran_conn; |
| 129 | |
| 130 | enum msc_role { |
| 131 | MSC_ROLE_A, |
| 132 | MSC_ROLE_I, |
| 133 | MSC_ROLE_T, |
| 134 | |
| 135 | MSC_ROLES_COUNT |
| 136 | }; |
| 137 | |
| 138 | extern const struct value_string msc_role_names[]; |
| 139 | static inline const char *msc_role_name(enum msc_role role) |
| 140 | { return get_value_string(msc_role_names, role); } |
| 141 | |
| 142 | |
| 143 | enum msc_common_events { |
| 144 | /* Explicitly start with 0 (first real event will be -1 + 1 = 0). */ |
| 145 | OFFSET_MSC_COMMON_EV = -1, |
| 146 | |
| 147 | MSC_REMOTE_EV_RX_GSUP, |
| 148 | |
| 149 | MSC_EV_CALL_LEG_RTP_LOCAL_ADDR_AVAILABLE, |
| 150 | MSC_EV_CALL_LEG_RTP_COMPLETE, |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 151 | MSC_EV_CALL_LEG_TERM, |
| 152 | |
| 153 | /* MNCC has told us to RTP_CREATE, but local RTP port has not yet been set up. |
| 154 | * The MSC role should respond by calling mncc_set_rtp_stream() */ |
| 155 | MSC_MNCC_EV_NEED_LOCAL_RTP, |
| 156 | MSC_MNCC_EV_CALL_PROCEEDING, |
| 157 | MSC_MNCC_EV_CALL_COMPLETE, |
| 158 | MSC_MNCC_EV_CALL_ENDED, |
| 159 | |
| 160 | LAST_MSC_COMMON_EV, |
| 161 | }; |
| 162 | |
| 163 | |
| 164 | /* The events that the msc_a_local and msc_a_remote FSM implementations can receive, |
| 165 | * according to specifications. Not all of these are necessarily implemented. */ |
| 166 | enum msc_a_events { |
| 167 | OFFSET_MSC_A_EV = LAST_MSC_COMMON_EV - 1, |
| 168 | |
| 169 | /* Establishing Layer 3 happens only at MSC-A (all-local MSC). To distinguish from the inter-MSC DTAP |
| 170 | * forwarding, keep this as a separate event. */ |
| 171 | MSC_A_EV_FROM_I_COMPLETE_LAYER_3, |
| 172 | |
| 173 | /* In inter-MSC situations, DTAP is forwarded transparently in AN-APDU IEs (formerly named |
| 174 | * BSS-APDU); see |
| 175 | * - 3GPP TS 49.008 4.2 'Transfer of DTAP and BSSMAP layer 3 messages on the * E-interface', |
| 176 | * - 3GPP TS 29.010 4.5.4 'BSSAP Messages transfer on E-Interface', |
| 177 | * - 3GPP TS 29.002 8.4.3 MAP_PROCESS_ACCESS_SIGNALLING service, 8.4.4 MAP_FORWARD_ACCESS_SIGNALLING service. |
| 178 | * |
| 179 | * MSC-B ---DTAP--> MSC-A MAP PROCESS ACCESS SIGNALLING request |
| 180 | * MSC-B <--DTAP--- MSC-A MAP FORWARD ACCESS SIGNALLING request |
| 181 | * (where neither will receive a "response") |
| 182 | * |
| 183 | * See 3GPP TS 49.008 6. 'BSSMAP messages transferred on the E-interface'. |
| 184 | * Depending on the RAN, the AN-APDU contains a BSSMAP or a RANAP encoded message. |
| 185 | * MSC-I to MSC-A: |
| 186 | * - Managing attach to one BSC+MSC: |
| 187 | * - CLASSMARK_UPDATE, |
| 188 | * - CIPHER_MODE_COMPLETE, |
| 189 | * - CIPHER_MODE_REJECT, |
| 190 | * - ASSIGNMENT_COMPLETE, |
| 191 | * - ASSIGNMENT_FAILURE, |
| 192 | * - CLEAR_REQUEST, |
| 193 | * - Handover related messages: |
| 194 | * - HANDOVER_REQUEST, |
| 195 | * - HANDOVER_PERFORMED, |
| 196 | * - HANDOVER_FAILURE, |
| 197 | * - Messages we don't need/support yet: |
| 198 | * - CHANNEL_MODIFY_REQUEST (MSC assisted codec changing handover), |
| 199 | * - SAPI_N_REJECT, |
| 200 | * - CONFUSION, |
| 201 | * - BSS_INVOKE_TRACE, |
| 202 | * - QUEUING_INDICATION, |
| 203 | * - PERFORM_LOCATION_REQUEST (*not* related to a Location Updating, but about passing the MS's geological |
| 204 | * position) |
| 205 | * - PERFORM_LOCATION_ABORT, |
| 206 | * - PERFORM_LOCATION_RESPONSE, |
| 207 | * - CONNECTION_ORIENTED_INFORMATION is listed in 48.008 3.2.1.70 as "(void)", |
| 208 | */ |
| 209 | MSC_A_EV_FROM_I_PROCESS_ACCESS_SIGNALLING_REQUEST, |
| 210 | MSC_A_EV_FROM_I_PREPARE_SUBSEQUENT_HANDOVER_REQUEST, |
| 211 | |
| 212 | /* See 3GPP TS 29.002 8.4.2 MAP_SEND_END_SIGNAL service. */ |
| 213 | MSC_A_EV_FROM_I_SEND_END_SIGNAL_REQUEST, |
| 214 | |
| 215 | /* These BSSMAP messages are relevant for MSC-T -> MSC-A, i.e. from the transitory during inter-MSC handover: |
| 216 | * |
| 217 | * - Handover related messages: |
| 218 | * - HANDOVER_REQUEST_ACKNOWLEDGE, |
| 219 | * - HANDOVER_COMPLETE, |
| 220 | * - HANDOVER_FAILURE, |
| 221 | * - HANDOVER_DETECT, |
| 222 | * - CLEAR_REQUEST, |
| 223 | * - Messages we don't need/support yet: |
| 224 | * - CONFUSION, |
| 225 | * - QUEUING_INDICATION, |
| 226 | */ |
| 227 | MSC_A_EV_FROM_T_PROCESS_ACCESS_SIGNALLING_REQUEST, |
| 228 | |
| 229 | /* Essentially the HO Request Ack. 3GPP TS 29.002 8.4.1 MAP_PREPARE_HANDOVER service. */ |
| 230 | MSC_A_EV_FROM_T_PREPARE_HANDOVER_RESPONSE, |
| 231 | MSC_A_EV_FROM_T_PREPARE_HANDOVER_FAILURE, |
| 232 | |
| 233 | /* Done establishing the radio link to the MS, for Handover. |
| 234 | * See 3GPP TS 29.002 8.4.2 MAP_SEND_END_SIGNAL service. |
| 235 | * Not to be confused with the MSC_I_EV_FROM_A_SEND_END_SIGNAL_RESPONSE that tells MSC-B to release. */ |
| 236 | MSC_A_EV_FROM_T_SEND_END_SIGNAL_REQUEST, |
| 237 | |
| 238 | /* gsm_04_08.c has successfully received a valid Complete Layer 3 message, i.e. Location Updating, CM Service |
Martin Hauke | 3f07dac | 2019-11-14 17:49:08 +0100 | [diff] [blame^] | 239 | * Request, Paging Response or IMSI Detach. */ |
Neels Hofmeyr | c4628a3 | 2018-12-07 14:47:34 +0100 | [diff] [blame] | 240 | MSC_A_EV_COMPLETE_LAYER_3_OK, |
| 241 | |
| 242 | /* Received a Classmark Update -- during GERAN ciphering, msc_a may have to wait for Classmark information to |
| 243 | * determine supported ciphers. */ |
| 244 | MSC_A_EV_CLASSMARK_UPDATE, |
| 245 | |
| 246 | /* LU or Process Access FSM have determined that the peer has verified its authenticity. */ |
| 247 | MSC_A_EV_AUTHENTICATED, |
| 248 | |
| 249 | /* A valid request is starting to be processed on the connection. Upon this event, msc_a moves from |
| 250 | * MSC_A_ST_AUTHENTICATED to MSC_A_ST_COMMUNICATING, and enters the only state without an expiry timeout. */ |
| 251 | MSC_A_EV_TRANSACTION_ACCEPTED, |
| 252 | |
| 253 | /* MSC originated close request, e.g. all done, failed authentication, ... */ |
| 254 | MSC_A_EV_CN_CLOSE, |
| 255 | |
| 256 | /* Subscriber originated close request */ |
| 257 | MSC_A_EV_MO_CLOSE, |
| 258 | |
| 259 | /* msc_a->use_count has reached a total of zero. */ |
| 260 | MSC_A_EV_UNUSED, |
| 261 | |
| 262 | MSC_A_EV_HANDOVER_REQUIRED, |
| 263 | MSC_A_EV_HANDOVER_END, |
| 264 | |
| 265 | /* indicates nr of MSC_A events, keep this as last enum value */ |
| 266 | LAST_MSC_A_EV |
| 267 | }; |
| 268 | osmo_static_assert(LAST_MSC_A_EV <= 32, not_too_many_msc_a_events); |
| 269 | |
| 270 | extern const struct value_string msc_a_fsm_event_names[]; |
| 271 | |
| 272 | enum msc_from_ran_events { |
| 273 | OFFSET_MSC_EV_FROM_RAN = LAST_MSC_COMMON_EV - 1, |
| 274 | |
| 275 | MSC_EV_FROM_RAN_COMPLETE_LAYER_3, |
| 276 | |
| 277 | /* A BSSMAP/RANAP message came in on the RAN conn. */ |
| 278 | MSC_EV_FROM_RAN_UP_L2, |
| 279 | |
| 280 | /* The RAN connection is gone, or busy going. */ |
| 281 | MSC_EV_FROM_RAN_CONN_RELEASED, |
| 282 | |
| 283 | LAST_MSC_EV_FROM_RAN |
| 284 | }; |
| 285 | |
| 286 | /* The events that the msc_i_local and msc_i_remote FSM implementations can receive. |
| 287 | * The MSC-I can also receive all msc_common_events and msc_from_ran_events. */ |
| 288 | enum msc_i_events { |
| 289 | OFFSET_E_MSC_I = LAST_MSC_EV_FROM_RAN - 1, |
| 290 | |
| 291 | /* BSSMAP/RANAP comes in from MSC-A to be sent out on the RAN conn. |
| 292 | * Depending on the RAN, the AN-APDU contains a BSSMAP or a RANAP encoded message. |
| 293 | * Relevant BSSMAP procedures, see 3GPP TS 49.008 6. 'BSSMAP messages transferred on the E-interface': |
| 294 | * - Managing attach to one BSC+MSC: |
| 295 | * - CLASSMARK_REQUEST, |
| 296 | * - CIPHER_MODE_COMMAND, |
| 297 | * - COMMON_ID, |
| 298 | * - ASSIGNMENT_REQUEST, |
| 299 | * - Handover related messages: |
| 300 | * - HANDOVER_REQUEST_ACKNOWLEDGE, |
| 301 | * - HANDOVER_FAILURE, |
| 302 | * - Messages we don't need/support yet: |
| 303 | * - CONFUSION, |
| 304 | * - MSC_INVOKE_TRACE, |
| 305 | * - QUEUING_INDICATION, |
| 306 | * - LSA_INFORMATION, |
| 307 | * - PERFORM_LOCATION_REQUEST, (*not* related to a Location Updating, but about passing the MS's geological position) |
| 308 | * - PERFORM_LOCATION_ABORT, |
| 309 | * - PERFORM_LOCATION_RESPONSE, |
| 310 | * - CONNECTION_ORIENTED_INFORMATION is listed in 48.008 3.2.1.70 as "(void)" |
| 311 | */ |
| 312 | MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST, |
| 313 | |
| 314 | /* MSC-A tells us to release the RAN connection. */ |
| 315 | MSC_I_EV_FROM_A_SEND_END_SIGNAL_RESPONSE, |
| 316 | |
| 317 | MSC_I_EV_FROM_A_PREPARE_SUBSEQUENT_HANDOVER_RESULT, |
| 318 | MSC_I_EV_FROM_A_PREPARE_SUBSEQUENT_HANDOVER_ERROR, |
| 319 | |
| 320 | LAST_MSC_I_EV |
| 321 | }; |
| 322 | osmo_static_assert(LAST_MSC_I_EV <= 32, not_too_many_msc_i_events); |
| 323 | |
| 324 | extern const struct value_string msc_i_fsm_event_names[]; |
| 325 | |
| 326 | /* The events that the msc_t_local and msc_t_remote FSM implementations can receive. |
| 327 | * The MSC-T can also receive all msc_common_events and msc_from_ran_events. */ |
| 328 | enum msc_t_events { |
| 329 | /* sufficient would be to use LAST_MSC_EV_FROM_RAN as offset. But while we have enough numbers |
| 330 | * available, it is a good idea to keep MSC-I and MSC-T events separate, to catch errors of |
| 331 | * sending wrong event kinds. */ |
| 332 | OFFSET_MSC_T_EV = LAST_MSC_I_EV - 1, |
| 333 | |
| 334 | /* BSSMAP/RANAP comes in from MSC-A to be sent out on the RAN conn. |
| 335 | * Relevant BSSMAP procedures, see 3GPP TS 49.008 6. 'BSSMAP messages transferred on the E-interface': |
| 336 | * - Handover related messages: |
| 337 | * - HANDOVER_REQUEST, |
| 338 | * - CLASSMARK_UPDATE, (?) |
| 339 | * - Messages we don't need/support yet: |
| 340 | * - CONFUSION, |
| 341 | * - MSC_INVOKE_TRACE, |
| 342 | * - BSS_INVOKE_TRACE, |
| 343 | */ |
| 344 | MSC_T_EV_FROM_A_PREPARE_HANDOVER_REQUEST, |
| 345 | MSC_T_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST, |
| 346 | |
| 347 | /* MSC originated close request, e.g. all done, failed handover, ... */ |
| 348 | MSC_T_EV_CN_CLOSE, |
| 349 | |
| 350 | /* Subscriber originated close request */ |
| 351 | MSC_T_EV_MO_CLOSE, |
| 352 | |
| 353 | MSC_T_EV_CLEAR_COMPLETE, |
| 354 | |
| 355 | LAST_MSC_T_EV |
| 356 | }; |
| 357 | osmo_static_assert(LAST_MSC_T_EV <= 32, not_too_many_msc_t_events); |
| 358 | |
| 359 | extern const struct value_string msc_t_fsm_event_names[]; |
| 360 | |
| 361 | /* All MSC role FSM implementations share this at the start of their fi->priv struct. |
| 362 | * See struct msc_a, struct msc_i, struct msc_t in their individual headers. */ |
| 363 | struct msc_role_common { |
| 364 | enum msc_role role; |
| 365 | |
| 366 | struct osmo_fsm_inst *fi; |
| 367 | |
| 368 | /* For a local implementation, this is NULL. Otherwise, this identifies how to reach the remote |
| 369 | * MSC that this "remote" implementation forwards messages to. */ |
| 370 | struct e_link *remote_to; |
| 371 | |
| 372 | struct msub *msub; |
| 373 | struct gsm_network *net; |
| 374 | struct ran_infra *ran; |
| 375 | }; |
| 376 | |
| 377 | /* AccessNetworkSignalInfo as in 3GPP TS 29.002. */ |
| 378 | struct an_apdu { |
| 379 | /* accessNetworkProtocolId */ |
| 380 | enum osmo_gsup_access_network_protocol an_proto; |
| 381 | /* signalInfo */ |
| 382 | struct msgb *msg; |
| 383 | /* If this AN-APDU is sent between MSCs, additional information from the E-interface messaging, like the |
| 384 | * Handover Number, will placed/available here. Otherwise may be left NULL. */ |
| 385 | const struct osmo_gsup_message *e_info; |
| 386 | }; |