aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom/bsc/handover_fsm.h
blob: f2ce732e950142b4b3d51cfdb4497134012822aa (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
/* Handover FSM API for intra-BSC and inter-BSC MT (to this BSC) Handover.
 * (For inter-BSC MO, from this BSC, see handover_inter_mo_fsm.c) */
#pragma once

#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/handover.h>

const char *handover_status(struct gsm_subscriber_connection *conn);

/* This macro automatically includes a final \n, if omitted. */
#define LOG_HO(conn, level, fmt, args...) do { \
	if (conn->ho.fi) \
		LOGPFSML(conn->ho.fi, level, "%s: " fmt "%s", \
			 handover_status(conn), \
			 ## args, LOG_ADD_NEWLINE(fmt)); \
	else \
		LOGP(DHODEC, level, "%s: " fmt "%s", \
		     handover_status(conn), \
		     ## args, LOG_ADD_NEWLINE(fmt)); \
	} while(0)

/* Terminology:
 * Intra-Cell: stays within one BTS, this should actually be an Assignment.
 * Intra-BSC: stays within one BSC, but moves between BTSes.
 * Inter-BSC: moves between BSCs.
 * Inter-BSC MO: Mobile Originated: move away from this BSC to another one.
 * Inter-BSC MT: Mobile Terminated: move from another BSC to this one.
 */

enum handover_fsm_state {
	HO_ST_NOT_STARTED,

	HO_ST_WAIT_LCHAN_ACTIVE,
	HO_ST_WAIT_RR_HO_DETECT,
	HO_ST_WAIT_RR_HO_COMPLETE,
	HO_ST_WAIT_LCHAN_ESTABLISHED,
	HO_ST_WAIT_MGW_ENDPOINT_TO_MSC,

	/* The inter-BSC MO Handover FSM has completely separate states, but since it makes sense for it
	 * to also live in conn->ho.fi, it should share the same event enum. From there it is merely
	 * cosmetic to just include the separate fairly trivial states in the same FSM definition.
	 * An inter-MO FSM is almost unnecessary. The sole reason is to wait whether the MSC indeed
	 * clears the conn, and if not to log and count a failed handover attempt. */
	MOHO_ST_WAIT_HO_COMMAND,
	MOHO_ST_WAIT_CLEAR,
};

enum handover_fsm_event {
	HO_EV_LCHAN_ACTIVE,
	HO_EV_LCHAN_ESTABLISHED,
	HO_EV_LCHAN_ERROR,
	HO_EV_RR_HO_DETECT,
	HO_EV_RR_HO_COMPLETE,
	HO_EV_RR_HO_FAIL,
	HO_EV_MSC_MGW_OK,
	HO_EV_MSC_MGW_FAIL,
	HO_EV_CONN_RELEASING,

	MOHO_EV_BSSMAP_HO_COMMAND,
};

struct moho_rx_bssmap_ho_command {
	const uint8_t *l3_info;
	const uint8_t l3_info_len;
};

/* To be sent along with the HO_EV_RR_HO_DETECT */
struct handover_rr_detect_data {
	struct msgb *msg;
	const uint8_t *access_delay;
};

void handover_start(struct handover_mo_req *req);
void handover_start_inter_bsc_mt(struct gsm_subscriber_connection *conn,
				 struct msgb *ho_request_msg);
void handover_end(struct gsm_subscriber_connection *conn, enum handover_result result);

const char *handover_status(struct gsm_subscriber_connection *conn);
bool handover_is_sane(struct gsm_subscriber_connection *conn, struct gsm_lchan *old_lchan,
		      struct gsm_lchan *new_lchan);