blob: 84eff07302e4606c1e2c7891797a72bc95cc5c1c [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);
182 msgb_free(an_apdu.msg);
183 return;
184}
185
186/* [MSC-A---------------------] [MSC-B---------------------]
187 * msc_a --> msc_{i,t}_remote ----GSUP---> msc_a_remote --> msc_{i,t} ---BSSMAP--> [BSS]
188 * ^you are here
189 */
190static void msc_a_remote_rx_gsup(struct msc_a *msc_a, const struct osmo_gsup_message *gsup_msg)
191{
192 struct msc_t *msc_t = msc_a_msc_t(msc_a);
193 struct msc_i *msc_i = msc_a_msc_i(msc_a);
194
195 /* If starting a new Handover, this subscriber *must* be new and completely unattached. Create a new msc_t role
196 * to receive below event. */
197 if (gsup_msg->message_type == OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_REQUEST) {
198 if (msc_t || msc_i) {
199 LOG_MSC_A_REMOTE_CAT(msc_a, DLGSUP, LOGL_ERROR,
200 "Already have an MSC-T or -I role, cannot Rx %s from remote MSC\n",
201 osmo_gsup_message_type_name(gsup_msg->message_type));
202 msc_a_remote_send_handover_failure(msc_a, GSM0808_CAUSE_EQUIPMENT_FAILURE);
203 return;
204 }
205
206 msc_t = msc_t_alloc_without_ran_peer(msc_a->c.msub, msc_a->c.ran);
207 }
208
209 /* 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
210 * messages from MSC-A *must* be intended for the MSC-T role. As soon as the Handover is successful, the MSC-T
211 * role disappears and an MSC-I role appears. */
212 if (msc_t) {
213 LOG_MSC_A_REMOTE_CAT(msc_a, DLGSUP, LOGL_DEBUG, "Routing to MSC-T: %s\n",
214 osmo_gsup_message_type_name(gsup_msg->message_type));
215 msc_a_remote_rx_gsup_to_msc_t(msc_a, gsup_msg);
216 } else if (msc_i) {
217 LOG_MSC_A_REMOTE_CAT(msc_a, DLGSUP, LOGL_DEBUG, "Routing to MSC-I: %s\n",
218 osmo_gsup_message_type_name(gsup_msg->message_type));
219 msc_a_remote_rx_gsup_to_msc_i(msc_a, gsup_msg);
220 } else {
221 LOG_MSC_A_REMOTE_CAT(msc_a, DLGSUP, LOGL_ERROR,
222 "No MSC-T nor MSC-I role present, cannot Rx GSUP %s\n",
223 osmo_gsup_message_type_name(gsup_msg->message_type));
224 }
225}
226
227static void msc_a_remote_fsm_communicating(struct osmo_fsm_inst *fi, uint32_t event, void *data)
228{
229 struct msc_a *msc_a = msc_a_remote_priv(fi);
230 struct an_apdu *an_apdu;
231
232 switch (event) {
233
234 case MSC_REMOTE_EV_RX_GSUP:
235 /* [MSC-A---------------------] [MSC-B---------------------]
236 * msc_a --> msc_{i,t}_remote ----GSUP---> msc_a_remote --> msc_{i,t} ---BSSMAP--> [BSS]
237 * ^you are here
238 */
239 msc_a_remote_rx_gsup(msc_a, (const struct osmo_gsup_message*)data);
240 return;
241
242 /* For all remaining cases:
243 * [MSC-A---------------------] [MSC-B---------------------]
244 * msc_a <-- msc_{i,t}_remote <---GSUP---- msc_a_remote <-- msc_{i,t} <--BSSMAP--- [BSS]
245 * you are here^
246 */
247
248 case MSC_A_EV_FROM_I_PROCESS_ACCESS_SIGNALLING_REQUEST:
249 an_apdu = data;
250 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_I,
251 OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST, an_apdu);
252 return;
253
254 case MSC_A_EV_FROM_I_PREPARE_SUBSEQUENT_HANDOVER_REQUEST:
255 an_apdu = data;
256 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_I,
257 OSMO_GSUP_MSGT_E_PREPARE_SUBSEQUENT_HANDOVER_REQUEST, an_apdu);
258 return;
259
260 case MSC_A_EV_FROM_I_SEND_END_SIGNAL_REQUEST:
261 an_apdu = data;
262 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_I,
263 OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST, an_apdu);
264 return;
265
266 case MSC_A_EV_FROM_T_PREPARE_HANDOVER_RESPONSE:
267 an_apdu = data;
268 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T,
269 OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_RESULT, an_apdu);
270 return;
271
272 case MSC_A_EV_FROM_T_PREPARE_HANDOVER_FAILURE:
273 an_apdu = data;
274 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T,
275 OSMO_GSUP_MSGT_E_PREPARE_HANDOVER_ERROR, an_apdu);
276 return;
277
278 case MSC_A_EV_FROM_T_PROCESS_ACCESS_SIGNALLING_REQUEST:
279 an_apdu = data;
280 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T,
281 OSMO_GSUP_MSGT_E_PROCESS_ACCESS_SIGNALLING_REQUEST, an_apdu);
282 return;
283
284 case MSC_A_EV_FROM_T_SEND_END_SIGNAL_REQUEST:
285 an_apdu = data;
286 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T,
287 OSMO_GSUP_MSGT_E_SEND_END_SIGNAL_REQUEST, an_apdu);
288 return;
289
290 case MSC_A_EV_CN_CLOSE:
291 case MSC_A_EV_MO_CLOSE:
292 osmo_fsm_inst_state_chg(msc_a->c.fi, MSC_A_ST_RELEASING, 0, 0);
293 return;
294
295 default:
296 OSMO_ASSERT(false);
297 }
298}
299
300static void msc_a_remote_fsm_releasing_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
301{
302 osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, fi);
303}
304
305static void msc_a_remote_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
306{
307 struct msc_a *msc_a = msc_a_remote_priv(fi);
308 if (msc_a->c.msub->role[MSC_ROLE_I])
309 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_I, OSMO_GSUP_MSGT_E_CLOSE, NULL);
310 if (msc_a->c.msub->role[MSC_ROLE_T])
311 msc_a_remote_msg_up_to_remote_msc(msc_a, MSC_ROLE_T, OSMO_GSUP_MSGT_E_CLOSE, NULL);
312}
313
314#define S(x) (1 << (x))
315
316/* FSM events are by definition compatible with msc_a_fsm. States could be a separate enum, but so that
317 * msc_a_is_accepted() also works on remote msc_a, this FSM shares state numbers with the msc_a_fsm_states. */
318static const struct osmo_fsm_state msc_a_remote_fsm_states[] = {
319 /* Whichever MSC_A_ST would be the first for the real MSC-A implementation, a fresh FSM instance will start in
320 * state == 0 and we just need to be able to transition out of it. */
321 [0] = {
322 .name = "INIT-REMOTE",
323 .out_state_mask = 0
324 | S(MSC_A_ST_COMMUNICATING)
325 | S(MSC_A_ST_RELEASING)
326 ,
327 },
328 [MSC_A_ST_COMMUNICATING] = {
329 .name = "COMMUNICATING",
330 .action = msc_a_remote_fsm_communicating,
331 .in_event_mask = 0
332 | S(MSC_REMOTE_EV_RX_GSUP)
333 | S(MSC_A_EV_FROM_I_PROCESS_ACCESS_SIGNALLING_REQUEST)
334 | S(MSC_A_EV_FROM_I_PREPARE_SUBSEQUENT_HANDOVER_REQUEST)
335 | S(MSC_A_EV_FROM_I_SEND_END_SIGNAL_REQUEST)
336 | S(MSC_A_EV_FROM_T_PREPARE_HANDOVER_RESPONSE)
337 | S(MSC_A_EV_FROM_T_PREPARE_HANDOVER_FAILURE)
338 | S(MSC_A_EV_FROM_T_PROCESS_ACCESS_SIGNALLING_REQUEST)
339 | S(MSC_A_EV_FROM_T_SEND_END_SIGNAL_REQUEST)
340 | S(MSC_A_EV_CN_CLOSE)
341 | S(MSC_A_EV_MO_CLOSE)
342 ,
343 .out_state_mask = 0
344 | S(MSC_A_ST_RELEASING)
345 ,
346 },
347 [MSC_A_ST_RELEASING] = {
348 .name = "RELEASING",
349 .onenter = msc_a_remote_fsm_releasing_onenter,
350 },
351};
352
353static struct osmo_fsm msc_a_remote_fsm = {
354 .name = "msc_a_remote",
355 .states = msc_a_remote_fsm_states,
356 .num_states = ARRAY_SIZE(msc_a_remote_fsm_states),
357 .log_subsys = DMSC,
358 .event_names = msc_a_fsm_event_names,
359 .cleanup = msc_a_remote_fsm_cleanup,
360};
361
362static __attribute__((constructor)) void msc_a_remote_fsm_init(void)
363{
364 OSMO_ASSERT(osmo_fsm_register(&msc_a_remote_fsm) == 0);
365}
366
367struct msc_a *msc_a_remote_alloc(struct msub *msub, struct ran_infra *ran,
368 const uint8_t *remote_msc_name, size_t remote_msc_name_len)
369{
370 struct msc_a *msc_a;
371
372 msub_role_alloc(msub, MSC_ROLE_A, &msc_a_remote_fsm, struct msc_a, ran);
373 msc_a = msub_msc_a(msub);
374 if (!msc_a) {
375 LOG_MSUB(msub, LOGL_ERROR, "Error setting up MSC-A remote role\n");
376 return NULL;
377 }
378
379 msc_a->c.remote_to = e_link_alloc(msub_net(msub)->gcm, msc_a->c.fi, remote_msc_name, remote_msc_name_len);
380 if (!msc_a->c.remote_to) {
381 LOG_MSC_A_REMOTE(msc_a, LOGL_ERROR, "Failed to set up E link\n");
382 msc_a_release_cn(msc_a);
383 return NULL;
384 }
385
386 msc_a_update_id(msc_a);
387
388 /* Immediately get out of state 0. */
389 osmo_fsm_inst_state_chg(msc_a->c.fi, MSC_A_ST_COMMUNICATING, 0, 0);
390
391 return msc_a;
392}