osmo-bsc/include/osmocom/bsc/handover_fsm.h

81 lines
2.5 KiB
C

/* Handover FSM API for intra-BSC and inter-BSC Handover. */
#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, \
handover_status(conn), ## args); \
else \
LOGP(DHODEC, level, "%s: " fmt, \
handover_status(conn), ## args); \
} 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 Out: move away from this BSC to another one.
* Inter-BSC In: 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 Outgoing 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-BSC Outgoing 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. */
HO_OUT_ST_WAIT_HO_COMMAND,
HO_OUT_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,
HO_OUT_EV_BSSMAP_HO_COMMAND,
};
struct ho_out_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_fsm_init();
void handover_request(struct handover_out_req *req);
void handover_start(struct handover_out_req *req);
void handover_start_inter_bsc_in(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);