blob: e4474f45dfebc0662ab0f7eabe7c1d357fc11561 [file] [log] [blame]
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001/* The MSC-A role implementation variant that forwards requests to/from a remote MSC. */
2/*
3 * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
4 * All Rights Reserved
5 *
6 * SPDX-License-Identifier: AGPL-3.0+
7 *
8 * Author: Neels Hofmeyr
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Affero General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
19 *
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24#include <inttypes.h>
25
26#include <osmocom/core/fsm.h>
27#include <osmocom/gsm/gsup.h>
28
29#include <osmocom/msc/debug.h>
30#include <osmocom/msc/gsm_data.h>
31#include <osmocom/msc/msc_a_remote.h>
32#include <osmocom/msc/msc_roles.h>
33#include <osmocom/msc/msub.h>
34#include <osmocom/msc/msc_a.h>
35#include <osmocom/msc/msc_t.h>
36#include <osmocom/msc/e_link.h>
37#include <osmocom/msc/vlr.h>
38#include <osmocom/msc/ran_peer.h>
39
40static struct osmo_fsm msc_a_remote_fsm;
41
42static struct msc_a *msc_a_remote_priv(struct osmo_fsm_inst *fi)
43{
44 OSMO_ASSERT(fi);
45 OSMO_ASSERT(fi->fsm == &msc_a_remote_fsm);
46 OSMO_ASSERT(fi->priv);
47 return fi->priv;
48}
49
50/* The idea is that this msc_a role is event-compatible to the "real" msc_a.c FSM, but instead of acting on the events
51 * directly, it forwards the events to a remote MSC-A role, via E-over-GSUP.
52 *
53 * [MSC-A---------------------] [MSC-B---------------------]
54 * msc_a <-- msc_{i,t}_remote <---GSUP---- msc_a_remote <-- msc_{i,t} <--BSSMAP--- [BSS]
55 * ^you are here
56 */
57static int msc_a_remote_msg_up_to_remote_msc(struct msc_a *msc_a,
58 enum msc_role from_role,
59 enum osmo_gsup_message_type message_type,
60 struct an_apdu *an_apdu)
61{
62 struct osmo_gsup_message m;
63 struct e_link *e = msc_a->c.remote_to;
64
65 if (!e) {
66 LOG_MSC_A_REMOTE(msc_a, LOGL_ERROR, "No E link to remote MSC, cannot send AN-APDU\n");
67 return -1;
68 }
69
70 if (e_prep_gsup_msg(e, &m)) {
71 LOG_MSC_A_REMOTE(msc_a, LOGL_ERROR, "Error composing E-interface GSUP message\n");
72 return -1;
73 }
74 m.message_type = message_type;
75 if (an_apdu) {
76 if (gsup_msg_assign_an_apdu(&m, an_apdu)) {
77 LOG_MSC_A_REMOTE(msc_a, LOGL_ERROR, "Error composing E-interface GSUP message\n");
78 return -1;
79 }
80 }
81
82 return e_tx(e, &m);
83}
84
85/* [MSC-A-----------------] [MSC-B-----------------]
86 * msc_a --> msc_t_remote ----GSUP---> msc_a_remote --> msc_t ---BSSMAP--> [BSS]
87 * ^you are here
88 */
89static void msc_a_remote_rx_gsup_to_msc_t(struct msc_a *msc_a, const struct osmo_gsup_message *gsup_msg)
90{
91 uint32_t event;
92 struct an_apdu an_apdu;
93
94 switch (gsup_msg->message_type) {
95 case OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST:
96 event = MSC_T_EV_FROM_A_PREPARE_HANDOVER_REQUEST;
97 break;
98
99 case OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST:
100 case OSMO_GSUP_MSGT_E_FORWARD_ACCESS_SIGNALLING_REQUEST:
101 event = MSC_T_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST;
102 break;
103
104 case OSMO_GSUP_MSGT_E_CLOSE:
105 case OSMO_GSUP_MSGT_E_ABORT:
106 case OSMO_GSUP_MSGT_E_ROUTING_ERROR:
107 /* TODO: maybe some non-"normal" release with error cause? */
108 msc_a_release_cn(msc_a);
109 return;
110
111 default:
112 LOG_MSC_A_REMOTE(msc_a, LOGL_ERROR, "Unhandled GSUP message type: %s\n",
113 osmo_gsup_message_type_name(gsup_msg->message_type));
114 return;
115 };
116
117 gsup_msg_to_an_apdu(&an_apdu, gsup_msg);
118 msub_role_dispatch(msc_a->c.msub, MSC_ROLE_T, event, &an_apdu);
119 if (an_apdu.msg)
120 msgb_free(an_apdu.msg);
121}
122
123/* [MSC-A-----------------] [MSC-B-----------------]
124 * msc_a --> msc_i_remote ----GSUP---> msc_a_remote --> msc_i ---BSSMAP--> [BSS]
125 * ^you are here
126 */
127static void msc_a_remote_rx_gsup_to_msc_i(struct msc_a *msc_a, const struct osmo_gsup_message *gsup_msg)
128{
129 uint32_t event;
130 struct an_apdu an_apdu;
131
132 switch (gsup_msg->message_type) {
133 case OSMO_GSUP_MSGT_E_FORWARD_ACCESS_SIGNALLING_REQUEST:
134 event = MSC_I_EV_FROM_A_FORWARD_ACCESS_SIGNALLING_REQUEST;
135 break;
136
137 case OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_ERROR:
138 case OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_RESULT:
139 event = MSC_I_EV_FROM_A_SEND_END_SIGNAL_RESPONSE;
140 break;
141
142 case OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_RESULT:
143 case OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_ERROR:
144 event = MSC_I_EV_FROM_A_PREPARE_SUBSEQUENT_HANDOVER_RESULT;
145 break;
146
147 case OSMO_GSUP_MSGT_E_CLOSE:
148 case OSMO_GSUP_MSGT_E_ABORT:
149 case OSMO_GSUP_MSGT_E_ROUTING_ERROR:
150 /* TODO: maybe some non-"normal" release with error cause? */
151 msc_a_release_cn(msc_a);
152 return;
153
154 default:
155 LOG_MSC_A_REMOTE(msc_a, LOGL_ERROR, "Unhandled GSUP message type: %s\n",
156 osmo_gsup_message_type_name(gsup_msg->message_type));
157 return;
158 };
159
160 gsup_msg_to_an_apdu(&an_apdu, gsup_msg);
161 msub_role_dispatch(msc_a->c.msub, MSC_ROLE_I, event, &an_apdu);
162 if (an_apdu.msg)
163 msgb_free(an_apdu.msg);
164}
165
166static void msc_a_remote_send_handover_failure(struct msc_a *msc_a, enum gsm0808_cause cause)
167{
168 struct ran_msg ran_enc_msg = {
169 .msg_type = RAN_MSG_HANDOVER_FAILURE,
170 .handover_failure = {
171 .cause = cause,
172 },
173 };
174 struct an_apdu an_apdu = {
175 .an_proto = msc_a->c.ran->an_proto,
176 .msg = msc_role_ran_encode(msc_a->c.fi, &ran_enc_msg),
177 };
178 if (!an_apdu.msg)
179 return;
180
181 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T, OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_ERROR, &an_apdu);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100182}
183
184/* [MSC-A---------------------] [MSC-B---------------------]
185 * msc_a --> msc_{i,t}_remote ----GSUP---> msc_a_remote --> msc_{i,t} ---BSSMAP--> [BSS]
186 * ^you are here
187 */
188static void msc_a_remote_rx_gsup(struct msc_a *msc_a, const struct osmo_gsup_message *gsup_msg)
189{
190 struct msc_t *msc_t = msc_a_msc_t(msc_a);
191 struct msc_i *msc_i = msc_a_msc_i(msc_a);
192
193 /* If starting a new Handover, this subscriber *must* be new and completely unattached. Create a new msc_t role
194 * to receive below event. */
195 if (gsup_msg->message_type == OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST) {
196 if (msc_t || msc_i) {
197 LOG_MSC_A_REMOTE_CAT(msc_a, DLGSUP, LOGL_ERROR,
198 "Already have an MSC-T or -I role, cannot Rx %s from remote MSC\n",
199 osmo_gsup_message_type_name(gsup_msg->message_type));
200 msc_a_remote_send_handover_failure(msc_a, GSM0808_CAUSE_EQUIPMENT_FAILURE);
201 return;
202 }
203
204 msc_t = msc_t_alloc_without_ran_peer(msc_a->c.msub, msc_a->c.ran);
205 }
206
207 /* We are on a remote MSC-B. If an msub has an MSC-T role, this is the remote target of a handover, and all
208 * messages from MSC-A *must* be intended for the MSC-T role. As soon as the Handover is successful, the MSC-T
209 * role disappears and an MSC-I role appears. */
210 if (msc_t) {
211 LOG_MSC_A_REMOTE_CAT(msc_a, DLGSUP, LOGL_DEBUG, "Routing to MSC-T: %s\n",
212 osmo_gsup_message_type_name(gsup_msg->message_type));
213 msc_a_remote_rx_gsup_to_msc_t(msc_a, gsup_msg);
214 } else if (msc_i) {
215 LOG_MSC_A_REMOTE_CAT(msc_a, DLGSUP, LOGL_DEBUG, "Routing to MSC-I: %s\n",
216 osmo_gsup_message_type_name(gsup_msg->message_type));
217 msc_a_remote_rx_gsup_to_msc_i(msc_a, gsup_msg);
218 } else {
219 LOG_MSC_A_REMOTE_CAT(msc_a, DLGSUP, LOGL_ERROR,
220 "No MSC-T nor MSC-I role present, cannot Rx GSUP %s\n",
221 osmo_gsup_message_type_name(gsup_msg->message_type));
222 }
223}
224
225static void msc_a_remote_fsm_communicating(struct osmo_fsm_inst *fi, uint32_t event, void *data)
226{
227 struct msc_a *msc_a = msc_a_remote_priv(fi);
228 struct an_apdu *an_apdu;
229
230 switch (event) {
231
232 case MSC_REMOTE_EV_RX_GSUP:
233 /* [MSC-A---------------------] [MSC-B---------------------]
234 * msc_a --> msc_{i,t}_remote ----GSUP---> msc_a_remote --> msc_{i,t} ---BSSMAP--> [BSS]
235 * ^you are here
236 */
237 msc_a_remote_rx_gsup(msc_a, (const struct osmo_gsup_message*)data);
238 return;
239
240 /* For all remaining cases:
241 * [MSC-A---------------------] [MSC-B---------------------]
242 * msc_a <-- msc_{i,t}_remote <---GSUP---- msc_a_remote <-- msc_{i,t} <--BSSMAP--- [BSS]
243 * you are here^
244 */
245
246 case MSC_A_EV_FROM_I_PROCESS_ACCESS_SIGNALLING_REQUEST:
247 an_apdu = data;
248 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_I,
249 OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST, an_apdu);
250 return;
251
252 case MSC_A_EV_FROM_I_PREPARE_SUBSEQUENT_HANDOVER_REQUEST:
253 an_apdu = data;
254 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_I,
255 OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_REQUEST, an_apdu);
256 return;
257
258 case MSC_A_EV_FROM_I_SEND_END_SIGNAL_REQUEST:
259 an_apdu = data;
260 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_I,
261 OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST, an_apdu);
262 return;
263
264 case MSC_A_EV_FROM_T_PREPARE_HANDOVER_RESPONSE:
265 an_apdu = data;
266 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T,
267 OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_RESULT, an_apdu);
268 return;
269
270 case MSC_A_EV_FROM_T_PREPARE_HANDOVER_FAILURE:
271 an_apdu = data;
272 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T,
273 OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_ERROR, an_apdu);
274 return;
275
276 case MSC_A_EV_FROM_T_PROCESS_ACCESS_SIGNALLING_REQUEST:
277 an_apdu = data;
278 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T,
279 OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST, an_apdu);
280 return;
281
282 case MSC_A_EV_FROM_T_SEND_END_SIGNAL_REQUEST:
283 an_apdu = data;
284 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T,
285 OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST, an_apdu);
286 return;
287
288 case MSC_A_EV_CN_CLOSE:
289 case MSC_A_EV_MO_CLOSE:
290 osmo_fsm_inst_state_chg(msc_a->c.fi, MSC_A_ST_RELEASING, 0, 0);
291 return;
292
293 default:
294 OSMO_ASSERT(false);
295 }
296}
297
298static void msc_a_remote_fsm_releasing_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
299{
300 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, fi);
301}
302
303static void msc_a_remote_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
304{
305 struct msc_a *msc_a = msc_a_remote_priv(fi);
306 if (msc_a->c.msub->role[MSC_ROLE_I])
307 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_I, OSMO_GSUP_MSGT_E_CLOSE, NULL);
308 if (msc_a->c.msub->role[MSC_ROLE_T])
309 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T, OSMO_GSUP_MSGT_E_CLOSE, NULL);
310}
311
312#define S(x) (1 << (x))
313
314/* FSM events are by definition compatible with msc_a_fsm. States could be a separate enum, but so that
315 * msc_a_is_accepted() also works on remote msc_a, this FSM shares state numbers with the msc_a_fsm_states. */
316static const struct osmo_fsm_state msc_a_remote_fsm_states[] = {
317 /* Whichever MSC_A_ST would be the first for the real MSC-A implementation, a fresh FSM instance will start in
318 * state == 0 and we just need to be able to transition out of it. */
319 [0] = {
320 .name = "INIT-REMOTE",
321 .out_state_mask = 0
322 | S(MSC_A_ST_COMMUNICATING)
323 | S(MSC_A_ST_RELEASING)
324 ,
325 },
326 [MSC_A_ST_COMMUNICATING] = {
327 .name = "COMMUNICATING",
328 .action = msc_a_remote_fsm_communicating,
329 .in_event_mask = 0
330 | S(MSC_REMOTE_EV_RX_GSUP)
331 | S(MSC_A_EV_FROM_I_PROCESS_ACCESS_SIGNALLING_REQUEST)
332 | S(MSC_A_EV_FROM_I_PREPARE_SUBSEQUENT_HANDOVER_REQUEST)
333 | S(MSC_A_EV_FROM_I_SEND_END_SIGNAL_REQUEST)
334 | S(MSC_A_EV_FROM_T_PREPARE_HANDOVER_RESPONSE)
335 | S(MSC_A_EV_FROM_T_PREPARE_HANDOVER_FAILURE)
336 | S(MSC_A_EV_FROM_T_PROCESS_ACCESS_SIGNALLING_REQUEST)
337 | S(MSC_A_EV_FROM_T_SEND_END_SIGNAL_REQUEST)
338 | S(MSC_A_EV_CN_CLOSE)
339 | S(MSC_A_EV_MO_CLOSE)
340 ,
341 .out_state_mask = 0
342 | S(MSC_A_ST_RELEASING)
343 ,
344 },
345 [MSC_A_ST_RELEASING] = {
346 .name = "RELEASING",
347 .onenter = msc_a_remote_fsm_releasing_onenter,
348 },
349};
350
351static struct osmo_fsm msc_a_remote_fsm = {
352 .name = "msc_a_remote",
353 .states = msc_a_remote_fsm_states,
354 .num_states = ARRAY_SIZE(msc_a_remote_fsm_states),
355 .log_subsys = DMSC,
356 .event_names = msc_a_fsm_event_names,
357 .cleanup = msc_a_remote_fsm_cleanup,
358};
359
360static __attribute__((constructor)) void msc_a_remote_fsm_init(void)
361{
362 OSMO_ASSERT(osmo_fsm_register(&msc_a_remote_fsm) == 0);
363}
364
365struct msc_a *msc_a_remote_alloc(struct msub *msub, struct ran_infra *ran,
366 const uint8_t *remote_msc_name, size_t remote_msc_name_len)
367{
368 struct msc_a *msc_a;
369
370 msub_role_alloc(msub, MSC_ROLE_A, &msc_a_remote_fsm, struct msc_a, ran);
371 msc_a = msub_msc_a(msub);
372 if (!msc_a) {
373 LOG_MSUB(msub, LOGL_ERROR, "Error setting up MSC-A remote role\n");
374 return NULL;
375 }
376
377 msc_a->c.remote_to = e_link_alloc(msub_net(msub)->gcm, msc_a->c.fi, remote_msc_name, remote_msc_name_len);
378 if (!msc_a->c.remote_to) {
379 LOG_MSC_A_REMOTE(msc_a, LOGL_ERROR, "Failed to set up E link\n");
380 msc_a_release_cn(msc_a);
381 return NULL;
382 }
383
384 msc_a_update_id(msc_a);
385
386 /* Immediately get out of state 0. */
387 osmo_fsm_inst_state_chg(msc_a->c.fi, MSC_A_ST_COMMUNICATING, 0, 0);
388
389 return msc_a;
390}