blob: 86044433407eda08ad8eb6772b64ba6c0ecef1f9 [file] [log] [blame]
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01001/*
Vadim Yanitskiy999a5932023-05-18 17:22:26 +07002 * (C) 2019 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +01003 * All Rights Reserved
4 *
5 * SPDX-License-Identifier: AGPL-3.0+
6 *
7 * Author: Neels Hofmeyr
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23#include <osmocom/core/linuxlist.h>
24#include <osmocom/core/logging.h>
25#include <osmocom/core/fsm.h>
26#include <osmocom/sigtran/sccp_helpers.h>
27
28#include <osmocom/msc/ran_peer.h>
29#include <osmocom/msc/sccp_ran.h>
30#include <osmocom/msc/msub.h>
31#include <osmocom/msc/msc_i.h>
32#include <osmocom/msc/msc_a.h>
33#include <osmocom/msc/vlr.h>
34#include <osmocom/msc/ran_conn.h>
35#include <osmocom/msc/cell_id_list.h>
Andreas Eversberg6c8db1d2023-04-23 12:00:16 +020036#include <osmocom/msc/msc_vgcs.h>
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010037
38static struct osmo_fsm ran_peer_fsm;
39
40static __attribute__((constructor)) void ran_peer_init()
41{
42 OSMO_ASSERT( osmo_fsm_register(&ran_peer_fsm) == 0);
43}
44
45/* Allocate a RAN peer with FSM instance. To deallocate, call osmo_fsm_inst_term(ran_peer->fi). */
46static struct ran_peer *ran_peer_alloc(struct sccp_ran_inst *sri, const struct osmo_sccp_addr *peer_addr)
47{
48 struct ran_peer *rp;
49 struct osmo_fsm_inst *fi;
50 char *sccp_addr;
51 char *pos;
52
53 fi = osmo_fsm_inst_alloc(&ran_peer_fsm, sri, NULL, LOGL_DEBUG, NULL);
54 OSMO_ASSERT(fi);
55
56 /* Unfortunately, osmo_sccp_inst_addr_name() returns "RI=SSN_PC,PC=0.24.1,SSN=BSSAP" but neither commas nor
57 * full-stops are allowed as FSM inst id. Make it "RI=SSN_PC:PC-0-24-1:SSN-BSSAP". */
58 sccp_addr = osmo_sccp_inst_addr_name(sri->sccp, peer_addr);
59 for (pos = sccp_addr; *pos; pos++) {
60 if (*pos == ',')
61 *pos = ':';
62 else if (*pos == '.' || *pos == '=')
63 *pos = '-';
64 }
65 osmo_fsm_inst_update_id_f(fi, "%s:%s", osmo_rat_type_name(sri->ran->type), sccp_addr);
66
67 rp = talloc_zero(fi, struct ran_peer);
68 OSMO_ASSERT(rp);
69 *rp = (struct ran_peer){
70 .sri = sri,
71 .peer_addr = *peer_addr,
72 .fi = fi,
73 };
74 INIT_LLIST_HEAD(&rp->cells_seen);
75 fi->priv = rp;
76
77 llist_add(&rp->entry, &sri->ran_peers);
78
79 return rp;
80}
81
82struct ran_peer *ran_peer_find_or_create(struct sccp_ran_inst *sri, const struct osmo_sccp_addr *peer_addr)
83{
Neels Hofmeyrcbcfe992020-09-23 01:32:11 +020084 struct ran_peer *rp = ran_peer_find_by_addr(sri, peer_addr);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010085 if (rp)
86 return rp;
87 return ran_peer_alloc(sri, peer_addr);
88}
89
Neels Hofmeyrcbcfe992020-09-23 01:32:11 +020090struct ran_peer *ran_peer_find_by_addr(struct sccp_ran_inst *sri, const struct osmo_sccp_addr *peer_addr)
Neels Hofmeyrc4628a32018-12-07 14:47:34 +010091{
92 struct ran_peer *rp;
93 llist_for_each_entry(rp, &sri->ran_peers, entry) {
94 if (osmo_sccp_addr_ri_cmp(peer_addr, &rp->peer_addr))
95 continue;
96 return rp;
97 }
98 return NULL;
99}
100
101void ran_peer_cells_seen_add(struct ran_peer *ran_peer, const struct gsm0808_cell_id *cid)
102{
103 if (!cell_id_list_add_cell(ran_peer, &ran_peer->cells_seen, cid))
104 return;
105 LOG_RAN_PEER_CAT(ran_peer, DPAG, LOGL_NOTICE, "Added seen cell to this RAN peer: %s\n",
106 gsm0808_cell_id_name(cid));
107}
108
109static const struct osmo_tdef_state_timeout ran_peer_fsm_timeouts[32] = {
110 [RAN_PEER_ST_WAIT_RX_RESET_ACK] = { .T = -1 },
111 [RAN_PEER_ST_DISCARDING] = { .T = -2 },
112};
113
114#define ran_peer_state_chg(RAN_PEER, NEXT_STATE) \
115 osmo_tdef_fsm_inst_state_chg((RAN_PEER)->fi, NEXT_STATE, ran_peer_fsm_timeouts, g_sccp_tdefs, 5)
116
117void ran_peer_discard_all_conns(struct ran_peer *rp)
118{
119 struct ran_conn *conn, *next;
120
121 ran_peer_for_each_ran_conn_safe(conn, next, rp) {
Andreas Eversbergb2652472023-06-14 09:22:23 +0200122 /* Tell VGCS FSM that the connections have been cleared. */
123 if (conn->vgcs.bss)
124 vgcs_vbs_clear_cpl(conn->vgcs.bss, NULL);
125 else if (conn->vgcs.cell)
126 vgcs_vbs_clear_cpl_channel(conn->vgcs.cell, NULL);
127 else ran_conn_discard(conn);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100128 }
129}
130
Neels Hofmeyrb6972742020-06-26 15:20:51 +0200131static void ran_peer_update_osmux_support(struct ran_peer *rp, int supports_osmux)
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200132{
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200133 bool old_value = rp->remote_supports_osmux;
134
Neels Hofmeyrb6972742020-06-26 15:20:51 +0200135 switch (supports_osmux) {
136 case 1:
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200137 rp->remote_supports_osmux = true;
Neels Hofmeyrb6972742020-06-26 15:20:51 +0200138 break;
139 case -1:
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200140 rp->remote_supports_osmux = false;
Neels Hofmeyrb6972742020-06-26 15:20:51 +0200141 break;
142 default:
143 return;
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200144 }
145
146 if (old_value != rp->remote_supports_osmux)
147 LOG_RAN_PEER(rp, LOGL_INFO, "BSC detected AoIP Osmux support changed: %d->%d\n",
148 old_value, rp->remote_supports_osmux);
149}
150
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100151/* Drop all SCCP connections for this ran_peer, respond with RESET ACKNOWLEDGE and move to READY state. */
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200152static void ran_peer_rx_reset(struct ran_peer *rp, struct msgb* msg)
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100153{
154 struct msgb *reset_ack;
155
156 ran_peer_discard_all_conns(rp);
157
158 reset_ack = rp->sri->ran->sccp_ran_ops.make_reset_msg(rp->sri, SCCP_RAN_MSG_RESET_ACK);
159
160 if (!reset_ack) {
161 LOG_RAN_PEER(rp, LOGL_ERROR, "Failed to compose RESET ACKNOWLEDGE message\n");
162 ran_peer_state_chg(rp, RAN_PEER_ST_WAIT_RX_RESET);
163 return;
164 }
165
166 if (sccp_ran_down_l2_cl(rp->sri, &rp->peer_addr, reset_ack)) {
167 LOG_RAN_PEER(rp, LOGL_ERROR, "Failed to send RESET ACKNOWLEDGE message\n");
168 ran_peer_state_chg(rp, RAN_PEER_ST_WAIT_RX_RESET);
Vadim Yanitskiy53d3e0e2019-05-10 02:44:57 +0700169 msgb_free(reset_ack);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100170 return;
171 }
172
173 LOG_RAN_PEER(rp, LOGL_INFO, "Sent RESET ACKNOWLEDGE\n");
174
Vadim Yanitskiy53d3e0e2019-05-10 02:44:57 +0700175 /* sccp_ran_down_l2_cl() doesn't free msgb */
176 msgb_free(reset_ack);
177
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100178 ran_peer_state_chg(rp, RAN_PEER_ST_READY);
179}
180
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200181static void ran_peer_rx_reset_ack(struct ran_peer *rp, struct msgb* msg)
Pau Espin Pedrolf15852b2019-05-13 19:54:02 +0200182{
183 ran_peer_state_chg(rp, RAN_PEER_ST_READY);
184}
185
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100186void ran_peer_reset(struct ran_peer *rp)
187{
188 struct msgb *reset;
189
190 ran_peer_state_chg(rp, RAN_PEER_ST_WAIT_RX_RESET_ACK);
191 ran_peer_discard_all_conns(rp);
192
193 reset = rp->sri->ran->sccp_ran_ops.make_reset_msg(rp->sri, SCCP_RAN_MSG_RESET);
194
195 if (!reset) {
196 LOG_RAN_PEER(rp, LOGL_ERROR, "Failed to compose RESET message\n");
197 ran_peer_state_chg(rp, RAN_PEER_ST_WAIT_RX_RESET);
198 return;
199 }
200
201 if (sccp_ran_down_l2_cl(rp->sri, &rp->peer_addr, reset)) {
202 LOG_RAN_PEER(rp, LOGL_ERROR, "Failed to send RESET message\n");
203 ran_peer_state_chg(rp, RAN_PEER_ST_WAIT_RX_RESET);
204 return;
205 }
206}
207
208void ran_peer_allstate_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
209{
210 struct ran_peer *rp = fi->priv;
211 struct ran_peer_ev_ctx *ctx = data;
212 struct msgb *msg = ctx->msg;
Neels Hofmeyr59de1562020-07-04 01:49:10 +0200213 enum reset_msg_type is_reset;
Neels Hofmeyrb6972742020-06-26 15:20:51 +0200214 int supports_osmux;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100215
216 switch (event) {
217 case RAN_PEER_EV_MSG_UP_CL:
Neels Hofmeyr59de1562020-07-04 01:49:10 +0200218 is_reset = rp->sri->ran->sccp_ran_ops.is_reset_msg(rp->sri, fi, msg, &supports_osmux);
Neels Hofmeyrb6972742020-06-26 15:20:51 +0200219 ran_peer_update_osmux_support(rp, supports_osmux);
Neels Hofmeyr59de1562020-07-04 01:49:10 +0200220 switch (is_reset) {
221 case SCCP_RAN_MSG_RESET:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100222 osmo_fsm_inst_dispatch(fi, RAN_PEER_EV_RX_RESET, msg);
223 return;
Neels Hofmeyr59de1562020-07-04 01:49:10 +0200224 case SCCP_RAN_MSG_RESET_ACK:
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100225 osmo_fsm_inst_dispatch(fi, RAN_PEER_EV_RX_RESET_ACK, msg);
226 return;
227 default:
228 LOG_RAN_PEER(rp, LOGL_ERROR, "Unhandled ConnectionLess message received: %s\n",
229 rp->sri->ran->sccp_ran_ops.msg_name(rp->sri, msg));
230 return;
231 }
232
233 default:
234 LOG_RAN_PEER(rp, LOGL_ERROR, "Unhandled event: %s\n", osmo_fsm_event_name(&ran_peer_fsm, event));
235 return;
236 }
237}
238
239void clear_and_disconnect(struct ran_peer *rp, uint32_t conn_id)
240{
241 struct msgb *clear;
242 struct ran_msg ran_enc_msg = {
243 .msg_type = RAN_MSG_CLEAR_COMMAND,
244 .clear_command = {
245 .gsm0808_cause = GSM0808_CAUSE_EQUIPMENT_FAILURE,
246 },
247 };
248
249 clear = rp->sri->ran->ran_encode(rp->fi, &ran_enc_msg);
250 if (!clear
251 || sccp_ran_down_l2_co(rp->sri, conn_id, clear))
252 LOG_RAN_PEER(rp, LOGL_ERROR, "Cannot sent Clear command\n");
253
254 sccp_ran_disconnect(rp->sri, conn_id, 0);
255}
256
257void ran_peer_st_wait_rx_reset(struct osmo_fsm_inst *fi, uint32_t event, void *data)
258{
259 struct ran_peer *rp = fi->priv;
260 struct ran_peer_ev_ctx *ctx;
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200261 struct msgb *msg;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100262
263 switch (event) {
264
265 case RAN_PEER_EV_MSG_UP_CO:
266 case RAN_PEER_EV_MSG_UP_CO_INITIAL:
267 ctx = data;
268 OSMO_ASSERT(ctx);
269
270 if (rp->sri->ignore_missing_reset) {
271 LOG_RAN_PEER(rp, LOGL_ERROR, "Receiving CO message on RAN peer that has not done a proper RESET yet."
272 " Accepting RAN peer implicitly (legacy compat)\n");
273 ran_peer_state_chg(rp, RAN_PEER_ST_READY);
274 osmo_fsm_inst_dispatch(rp->fi, event, data);
275 return;
276 }
277
278 LOG_RAN_PEER(rp, LOGL_ERROR, "Receiving CO message on RAN peer that has not done a proper RESET yet."
279 " Disconnecting on incoming message, sending RESET to RAN peer.\n");
280 /* No valid RESET procedure has happened here yet. Usually, we're expecting the RAN peer (BSC,
281 * RNC) to first send a RESET message before sending Connection Oriented messages. So if we're
282 * getting a CO message, likely we've just restarted or something. Send a RESET to the peer. */
283
284 /* Make sure the MS / UE properly disconnects. */
285 clear_and_disconnect(rp, ctx->conn_id);
286
287 ran_peer_reset(rp);
288 return;
289
290 case RAN_PEER_EV_RX_RESET:
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200291 msg = (struct msgb*)data;
292 ran_peer_rx_reset(rp, msg);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100293 return;
294
295 default:
296 LOG_RAN_PEER(rp, LOGL_ERROR, "Unhandled event: %s\n", osmo_fsm_event_name(&ran_peer_fsm, event));
297 return;
298 }
299}
300
301void ran_peer_st_wait_rx_reset_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
302{
303 struct ran_peer *rp = fi->priv;
304 struct ran_peer_ev_ctx *ctx;
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200305 struct msgb *msg;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100306
307 switch (event) {
308
309 case RAN_PEER_EV_RX_RESET_ACK:
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200310 msg = (struct msgb*)data;
311 ran_peer_rx_reset_ack(rp, msg);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100312 return;
313
314 case RAN_PEER_EV_MSG_UP_CO:
315 case RAN_PEER_EV_MSG_UP_CO_INITIAL:
316 ctx = data;
317 OSMO_ASSERT(ctx);
318 LOG_RAN_PEER(rp, LOGL_ERROR, "Receiving CO message on RAN peer that has not done a proper RESET yet."
319 " Disconnecting on incoming message, sending RESET to RAN peer.\n");
320 sccp_ran_disconnect(rp->sri, ctx->conn_id, 0);
321 /* No valid RESET procedure has happened here yet. */
322 ran_peer_reset(rp);
323 return;
324
325 case RAN_PEER_EV_RX_RESET:
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200326 msg = (struct msgb*)data;
327 ran_peer_rx_reset(rp, msg);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100328 return;
329
330 default:
331 LOG_RAN_PEER(rp, LOGL_ERROR, "Unhandled event: %s\n", osmo_fsm_event_name(&ran_peer_fsm, event));
332 return;
333 }
334}
335
336static struct ran_conn *new_incoming_conn(struct ran_peer *rp, uint32_t conn_id)
337{
338 struct gsm_network *net = rp->sri->user_data;
339 struct msub *msub;
340 struct msc_i *msc_i;
341 struct msc_a *msc_a;
342 struct ran_conn *ran_conn;
343
344 msub = msub_alloc(net);
345 OSMO_ASSERT(msub);
346 msc_i = msc_i_alloc(msub, rp->sri->ran);
347 OSMO_ASSERT(msc_i);
348
349 ran_conn = ran_conn_create_incoming(rp, conn_id);
350 if (!ran_conn) {
351 LOG_RAN_PEER(rp, LOGL_ERROR, "Cannot allocate ran_conn\n");
352 return NULL;
353 }
354 msc_i_set_ran_conn(msc_i, ran_conn);
355
356 msc_a = msc_a_alloc(msub, rp->sri->ran);
357 OSMO_ASSERT(msc_a);
358
359 return msc_i->ran_conn;
360}
361
362void ran_peer_st_ready(struct osmo_fsm_inst *fi, uint32_t event, void *data)
363{
364 struct ran_peer *rp = fi->priv;
365 struct ran_peer_ev_ctx *ctx;
366 struct ran_conn *conn;
367 struct an_apdu an_apdu;
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200368 struct msgb *msg;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100369
370 switch (event) {
371
372 case RAN_PEER_EV_MSG_UP_CO_INITIAL:
373 ctx = data;
Vadim Yanitskiyd14422a2019-07-09 00:37:49 +0700374 OSMO_ASSERT(ctx);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100375 OSMO_ASSERT(!ctx->conn);
376 OSMO_ASSERT(ctx->msg);
377
378 conn = new_incoming_conn(rp, ctx->conn_id);
379 if (!conn)
380 return;
381 if (!conn->msc_role) {
382 LOG_RAN_PEER(rp, LOGL_ERROR,
383 "Rx CO Initial message on conn that is not associated with any MSC role\n");
384 return;
385 }
386
387
388 an_apdu = (struct an_apdu){
389 .an_proto = rp->sri->ran->an_proto,
390 .msg = ctx->msg,
391 };
392
393 osmo_fsm_inst_dispatch(conn->msc_role, MSC_EV_FROM_RAN_COMPLETE_LAYER_3, &an_apdu);
394 return;
395
396 case RAN_PEER_EV_MSG_UP_CO:
397 ctx = data;
398 OSMO_ASSERT(ctx);
399 OSMO_ASSERT(ctx->conn);
400 OSMO_ASSERT(ctx->msg);
401
Andreas Eversberg6c8db1d2023-04-23 12:00:16 +0200402 if (ctx->conn->msc_role) {
403 /* "normal" A connection, dispatch to MSC-I or MSC-T */
404 an_apdu = (struct an_apdu){
405 .an_proto = rp->sri->ran->an_proto,
406 .msg = ctx->msg,
407 };
408 osmo_fsm_inst_dispatch(ctx->conn->msc_role, MSC_EV_FROM_RAN_UP_L2, &an_apdu);
409 } else if (ctx->conn->vgcs.bss) {
410 /* VGCS call related */
411 msc_a_rx_vgcs_bss(ctx->conn->vgcs.bss, ctx->conn, ctx->msg);
412 } else if (ctx->conn->vgcs.cell) {
413 /* VGCS channel related */
414 msc_a_rx_vgcs_cell(ctx->conn->vgcs.cell, ctx->conn, ctx->msg);
415 } else
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100416 LOG_RAN_PEER(rp, LOGL_ERROR,
417 "Rx CO message on conn that is not associated with any MSC role\n");
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100418 return;
419
420 case RAN_PEER_EV_MSG_DOWN_CO_INITIAL:
421 ctx = data;
422 OSMO_ASSERT(ctx);
423 OSMO_ASSERT(ctx->msg);
424 sccp_ran_down_l2_co_initial(rp->sri, &rp->peer_addr, ctx->conn_id, ctx->msg);
425 return;
426
427 case RAN_PEER_EV_MSG_DOWN_CO:
428 ctx = data;
429 OSMO_ASSERT(ctx);
430 OSMO_ASSERT(ctx->msg);
431 sccp_ran_down_l2_co(rp->sri, ctx->conn_id, ctx->msg);
432 return;
433
434 case RAN_PEER_EV_MSG_DOWN_CL:
435 OSMO_ASSERT(data);
436 sccp_ran_down_l2_cl(rp->sri, &rp->peer_addr, (struct msgb*)data);
437 return;
438
439 case RAN_PEER_EV_RX_RESET:
Pau Espin Pedrolf9f38b52019-05-07 11:48:16 +0200440 msg = (struct msgb*)data;
441 ran_peer_rx_reset(rp, msg);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100442 return;
443
444 default:
445 LOG_RAN_PEER(rp, LOGL_ERROR, "Unhandled event: %s\n", osmo_fsm_event_name(&ran_peer_fsm, event));
446 return;
447 }
448}
449
450static int ran_peer_fsm_timer_cb(struct osmo_fsm_inst *fi)
451{
452 struct ran_peer *rp = fi->priv;
453 ran_peer_state_chg(rp, RAN_PEER_ST_WAIT_RX_RESET);
454 return 0;
455}
456
457void ran_peer_fsm_cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
458{
459 struct ran_peer *rp = fi->priv;
460 ran_peer_discard_all_conns(rp);
461 llist_del(&rp->entry);
462}
463
464static const struct value_string ran_peer_fsm_event_names[] = {
465 OSMO_VALUE_STRING(RAN_PEER_EV_MSG_UP_CL),
466 OSMO_VALUE_STRING(RAN_PEER_EV_MSG_UP_CO_INITIAL),
467 OSMO_VALUE_STRING(RAN_PEER_EV_MSG_UP_CO),
468 OSMO_VALUE_STRING(RAN_PEER_EV_MSG_DOWN_CL),
469 OSMO_VALUE_STRING(RAN_PEER_EV_MSG_DOWN_CO_INITIAL),
470 OSMO_VALUE_STRING(RAN_PEER_EV_MSG_DOWN_CO),
471 OSMO_VALUE_STRING(RAN_PEER_EV_RX_RESET),
472 OSMO_VALUE_STRING(RAN_PEER_EV_RX_RESET_ACK),
473 OSMO_VALUE_STRING(RAN_PEER_EV_CONNECTION_SUCCESS),
474 OSMO_VALUE_STRING(RAN_PEER_EV_CONNECTION_TIMEOUT),
475 {}
476};
477
478#define S(x) (1 << (x))
479
480static const struct osmo_fsm_state ran_peer_fsm_states[] = {
481 [RAN_PEER_ST_WAIT_RX_RESET] = {
482 .name = "WAIT_RX_RESET",
483 .action = ran_peer_st_wait_rx_reset,
484 .in_event_mask = 0
485 | S(RAN_PEER_EV_RX_RESET)
486 | S(RAN_PEER_EV_MSG_UP_CO_INITIAL)
487 | S(RAN_PEER_EV_MSG_UP_CO)
488 | S(RAN_PEER_EV_CONNECTION_TIMEOUT)
489 ,
490 .out_state_mask = 0
491 | S(RAN_PEER_ST_WAIT_RX_RESET)
492 | S(RAN_PEER_ST_WAIT_RX_RESET_ACK)
493 | S(RAN_PEER_ST_READY)
494 | S(RAN_PEER_ST_DISCARDING)
495 ,
496 },
497 [RAN_PEER_ST_WAIT_RX_RESET_ACK] = {
498 .name = "WAIT_RX_RESET_ACK",
499 .action = ran_peer_st_wait_rx_reset_ack,
500 .in_event_mask = 0
501 | S(RAN_PEER_EV_RX_RESET)
502 | S(RAN_PEER_EV_RX_RESET_ACK)
503 | S(RAN_PEER_EV_MSG_UP_CO_INITIAL)
504 | S(RAN_PEER_EV_MSG_UP_CO)
505 | S(RAN_PEER_EV_CONNECTION_TIMEOUT)
506 ,
507 .out_state_mask = 0
508 | S(RAN_PEER_ST_WAIT_RX_RESET)
509 | S(RAN_PEER_ST_WAIT_RX_RESET_ACK)
510 | S(RAN_PEER_ST_READY)
511 | S(RAN_PEER_ST_DISCARDING)
512 ,
513 },
514 [RAN_PEER_ST_READY] = {
515 .name = "READY",
516 .action = ran_peer_st_ready,
517 .in_event_mask = 0
518 | S(RAN_PEER_EV_RX_RESET)
519 | S(RAN_PEER_EV_MSG_UP_CO_INITIAL)
520 | S(RAN_PEER_EV_MSG_UP_CO)
521 | S(RAN_PEER_EV_MSG_DOWN_CO_INITIAL)
522 | S(RAN_PEER_EV_MSG_DOWN_CO)
523 | S(RAN_PEER_EV_MSG_DOWN_CL)
524 ,
525 .out_state_mask = 0
526 | S(RAN_PEER_ST_WAIT_RX_RESET)
527 | S(RAN_PEER_ST_WAIT_RX_RESET_ACK)
528 | S(RAN_PEER_ST_READY)
529 | S(RAN_PEER_ST_DISCARDING)
530 ,
531 },
532 [RAN_PEER_ST_DISCARDING] = {
533 .name = "DISCARDING",
534 },
535};
536
537static struct osmo_fsm ran_peer_fsm = {
538 .name = "ran_peer",
539 .states = ran_peer_fsm_states,
540 .num_states = ARRAY_SIZE(ran_peer_fsm_states),
541 .log_subsys = DRR,
542 .event_names = ran_peer_fsm_event_names,
543 .timer_cb = ran_peer_fsm_timer_cb,
544 .cleanup = ran_peer_fsm_cleanup,
545 .allstate_action = ran_peer_allstate_action,
546 .allstate_event_mask = 0
547 | S(RAN_PEER_EV_MSG_UP_CL)
548 ,
549};
550
551int ran_peer_up_l2(struct sccp_ran_inst *sri, const struct osmo_sccp_addr *calling_addr, bool co, uint32_t conn_id,
552 struct msgb *l2)
553{
554 struct ran_peer *ran_peer = NULL;
555 uint32_t event;
556 struct ran_peer_ev_ctx ctx = {
557 .conn_id = conn_id,
558 .msg = l2,
559 };
560
561 if (co) {
562 struct ran_conn *conn;
563 llist_for_each_entry(conn, &sri->ran_conns, entry) {
564 if (conn->sccp_conn_id == conn_id) {
565 ran_peer = conn->ran_peer;
566 ctx.conn = conn;
567 break;
568 }
569 }
570
571 if (ran_peer && calling_addr) {
572 LOG_SCCP_RAN_CO(sri, calling_addr, conn_id, LOGL_ERROR,
573 "Connection-Oriented Initial message for already existing conn_id."
574 " Dropping message.\n");
575 return -EINVAL;
576 }
577
578 if (!ran_peer && !calling_addr) {
579 LOG_SCCP_RAN_CO(sri, calling_addr, conn_id, LOGL_ERROR,
580 "Connection-Oriented non-Initial message for unknown conn_id %u."
581 " Dropping message.\n", conn_id);
582 return -EINVAL;
583 }
584 }
585
586 if (calling_addr) {
587 ran_peer = ran_peer_find_or_create(sri, calling_addr);
588 if (!ran_peer) {
589 LOG_SCCP_RAN_CL(sri, calling_addr, LOGL_ERROR, "Cannot register RAN peer\n");
590 return -EIO;
591 }
592 }
593
594 OSMO_ASSERT(ran_peer && ran_peer->fi);
595
596 if (co)
597 event = calling_addr ? RAN_PEER_EV_MSG_UP_CO_INITIAL : RAN_PEER_EV_MSG_UP_CO;
598 else
599 event = RAN_PEER_EV_MSG_UP_CL;
600
601 return osmo_fsm_inst_dispatch(ran_peer->fi, event, &ctx);
602}
603
604void ran_peer_disconnect(struct sccp_ran_inst *sri, uint32_t conn_id)
605{
606 struct ran_conn *conn;
607 llist_for_each_entry(conn, &sri->ran_conns, entry) {
608 if (conn->sccp_conn_id == conn_id) {
609 ran_conn_discard(conn);
610 return;
611 }
612 }
613}
614
615struct ran_peer *ran_peer_find_by_cell_id(struct sccp_ran_inst *sri, const struct gsm0808_cell_id *cid,
616 bool expecting_single_match)
617{
618 struct ran_peer *rp;
619 struct ran_peer *found = NULL;
620
621 llist_for_each_entry(rp, &sri->ran_peers, entry) {
622 if (cell_id_list_find(&rp->cells_seen, cid, 0, false)) {
623 if (!expecting_single_match)
624 return rp;
625 /* Otherwise continue iterating and log errors for multiple matches... */
626 if (found) {
627 LOG_RAN_PEER(found, LOGL_ERROR, "Cell appears in more than one RAN peer:"
628 " %s also appears in %s\n",
629 gsm0808_cell_id_name(cid), rp->fi->id);
630 } else
631 found = rp;
632 }
633 }
634 return found;
635}
636
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100637int ran_peers_down_paging(struct sccp_ran_inst *sri, enum CELL_IDENT page_where, struct vlr_subscr *vsub,
638 enum paging_cause cause)
639{
640 struct ran_peer *rp;
641 int ret = 0;
642 struct gsm0808_cell_id page_id;
643 gsm0808_cell_id_from_cgi(&page_id, page_where, &vsub->cgi);
644
645 switch (page_where) {
646 case CELL_IDENT_NO_CELL:
Martin Hauke3f07dac2019-11-14 17:49:08 +0100647 LOG_SCCP_RAN_CAT(sri, DPAG, LOGL_ERROR, "Asked to page on NO_CELL, which doesn't make sense.\n");
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100648 return 0;
649
650 case CELL_IDENT_UTRAN_PLMN_LAC_RNC:
651 case CELL_IDENT_UTRAN_RNC:
652 case CELL_IDENT_UTRAN_LAC_RNC:
653 LOG_SCCP_RAN_CAT(sri, DPAG, LOGL_ERROR, "Don't know how to page on %s\n",
654 gsm0808_cell_id_name(&page_id));
655 return 0;
656
657 default:
658 break;
659 };
660
661 llist_for_each_entry(rp, &sri->ran_peers, entry) {
662 ret += ran_peer_down_paging(rp, &page_id, vsub, cause);
663 }
664
665 if (!ret)
666 LOG_SCCP_RAN_CAT(sri, DPAG, LOGL_ERROR, "Paging failed, no RAN peers found for %s\n",
667 gsm0808_cell_id_name(&page_id));
668 return ret;
669}
670
671/* If the given vsub->cgi matches this ran_peer with respect to page_where, page and return 1.
672 * Otherwise return 0. (Return value: number of pagings sent) */
673int ran_peer_down_paging(struct ran_peer *rp, const struct gsm0808_cell_id *page_id, struct vlr_subscr *vsub,
674 enum paging_cause cause)
675{
676 struct msgb *l2;
677
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100678 /* There are also the RAN peers that are configured in the neighbor ident for Handover, but if those aren't
679 * connected, then we can't Page there. */
Vadim Yanitskiyd24c46a2019-05-14 21:49:47 +0700680 if (!cell_id_list_find(&rp->cells_seen, page_id, 0, false))
681 return 0;
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100682
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100683 LOG_RAN_PEER_CAT(rp, DPAG, LOGL_DEBUG, "Paging for %s on %s\n", vlr_subscr_name(vsub),
684 gsm0808_cell_id_name(page_id));
685 l2 = rp->sri->ran->sccp_ran_ops.make_paging_msg(rp->sri, page_id, vsub->imsi, vsub->tmsi, cause);
686 if (osmo_fsm_inst_dispatch(rp->fi, RAN_PEER_EV_MSG_DOWN_CL, l2)) {
687 /* Not allowed to send messages, the peer is not properly connected yet/anymore */
688 LOG_RAN_PEER_CAT(rp, DPAG, LOGL_ERROR,
689 "Paging for %s matched this RAN peer, but emitting a Paging failed\n",
690 gsm0808_cell_id_name(page_id));
Vadim Yanitskiyede95d12019-05-14 21:41:06 +0700691 msgb_free(l2);
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100692 return 0;
693 }
Vadim Yanitskiyede95d12019-05-14 21:41:06 +0700694
695 /* The RAN_PEER_EV_MSG_DOWN_CL handler calls sccp_ran_down_l2_cl(),
696 * which doesn't free msgb. We have to do this ourselves. */
697 msgb_free(l2);
698
Neels Hofmeyrc4628a32018-12-07 14:47:34 +0100699 return 1;
700}