blob: d22ac869666f58f0854abd40cfa8761dc74df128 [file] [log] [blame]
Neels Hofmeyra2733ae2017-11-28 00:29:25 +01001#pragma once
Holger Hans Peter Freytherf2553a62010-06-30 12:58:14 +08002
Neels Hofmeyr45e46d22018-02-15 14:10:12 +01003#include <stdint.h>
4
5#include <osmocom/core/linuxlist.h>
6#include <osmocom/core/timer.h>
Harald Welte3561bd42018-01-28 03:04:16 +01007#include <osmocom/gsm/gsm_utils.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +02008#include <osmocom/gsm/gsm0808.h>
Neels Hofmeyr45e46d22018-02-15 14:10:12 +01009
Neels Hofmeyr19bed232018-03-22 04:54:57 +010010#include <osmocom/bsc/neighbor_ident.h>
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020011#include <osmocom/bsc/gsm_data.h>
Neels Hofmeyr19bed232018-03-22 04:54:57 +010012
Neels Hofmeyr91a202d2019-07-13 01:12:53 +020013#define LOG_HO(conn, level, fmt, args...) do { \
14 if (conn->ho.fi) \
15 LOGPFSML(conn->ho.fi, level, "%s: " fmt, \
16 handover_status(conn), ## args); \
17 else \
18 LOGP(DHODEC, level, "%s: " fmt, \
19 handover_status(conn), ## args); \
20 } while(0)
21
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020022struct gsm_network;
Neels Hofmeyra2733ae2017-11-28 00:29:25 +010023struct gsm_lchan;
24struct gsm_bts;
Holger Hans Peter Freytherf2553a62010-06-30 12:58:14 +080025struct gsm_subscriber_connection;
Harald Welte74632852020-04-20 19:58:53 +020026struct gsm_meas_rep;
Holger Hans Peter Freytherf2553a62010-06-30 12:58:14 +080027
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020028enum handover_result {
29 HO_RESULT_OK,
30 HO_RESULT_FAIL_NO_CHANNEL,
31 HO_RESULT_FAIL_RR_HO_FAIL,
32 HO_RESULT_FAIL_TIMEOUT,
33 HO_RESULT_CONN_RELEASE,
34 HO_RESULT_ERROR,
Neels Hofmeyr45e46d22018-02-15 14:10:12 +010035};
36
Neels Hofmeyr91a202d2019-07-13 01:12:53 +020037const char *handover_status(struct gsm_subscriber_connection *conn);
38
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020039extern const struct value_string handover_result_names[];
40inline static const char *handover_result_name(enum handover_result val)
41{ return get_value_string(handover_result_names, val); }
Neels Hofmeyr45e46d22018-02-15 14:10:12 +010042
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020043int bts_handover_count(struct gsm_bts *bts, int ho_scopes);
Neels Hofmeyr45e46d22018-02-15 14:10:12 +010044
45/* Handover decision algorithms' actions to take on incoming handover-relevant events.
46 *
47 * All events that are interesting for handover decision are actually communicated by S_LCHAN_* signals,
48 * so theoretically, each handover algorithm could evaluate those. However, handover_logic.c cleans up
49 * handover operation state upon receiving some of these signals. To allow a handover decision algorithm
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020050 * to take advantage of e.g. the struct handover before it is discarded, the handover decision event
Neels Hofmeyr45e46d22018-02-15 14:10:12 +010051 * handler needs to be invoked before handover_logic.c discards the state. For example, if the handover
52 * decision wants to place a penalty timer upon a handover failure, it still needs to know which target
53 * cell the handover failed for; handover_logic.c erases that knowledge on handover failure, since it
54 * needs to clean up the lchan's handover state.
55 *
56 * The most explicit and safest way to ensure the correct order of event handling is to invoke the
57 * handover decision algorithm's actions from handover_logic.c itself, before cleaning up. This struct
58 * provides the callback functions for this purpose.
59 *
60 * For consistency, also handle signals in this way that aren't actually in danger of interference from
61 * handover_logic.c (which also saves repeated lookup of handover state for lchans). Thus, handover
62 * decision algorithms should not register any signal handler at all.
63 */
64struct handover_decision_callbacks {
65 struct llist_head entry;
66
67 int hodec_id;
68
69 void (*on_measurement_report)(struct gsm_meas_rep *mr);
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020070 void (*on_handover_end)(struct gsm_subscriber_connection *conn, enum handover_result result);
Neels Hofmeyr45e46d22018-02-15 14:10:12 +010071};
72
73void handover_decision_callbacks_register(struct handover_decision_callbacks *hdc);
74struct handover_decision_callbacks *handover_decision_callbacks_get(int hodec_id);
Neels Hofmeyr19bed232018-03-22 04:54:57 +010075
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020076int bsc_tx_bssmap_ho_required(struct gsm_lchan *lchan, const struct gsm0808_cell_id_list2 *target_cells);
77int bsc_tx_bssmap_ho_request_ack(struct gsm_subscriber_connection *conn,
78 struct msgb *rr_ho_command);
79int bsc_tx_bssmap_ho_detect(struct gsm_subscriber_connection *conn);
80enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection *conn,
81 struct gsm_lchan *lchan);
82void bsc_tx_bssmap_ho_failure(struct gsm_subscriber_connection *conn);
83
Neels Hofmeyr91a202d2019-07-13 01:12:53 +020084int find_handover_target_cell(struct gsm_bts **local_target_cell_p,
85 const struct gsm0808_cell_id_list2 **remote_target_cell_p,
86 struct gsm_subscriber_connection *conn, const struct neighbor_ident_key *search_for,
87 bool log_errors);
88
Neels Hofmeyr19bed232018-03-22 04:54:57 +010089struct neighbor_ident_key *bts_ident_key(const struct gsm_bts *bts);
Neels Hofmeyr31f525e2018-05-14 18:14:15 +020090
91void handover_parse_inter_bsc_mt(struct gsm_subscriber_connection *conn,
92 struct msgb *ho_request_msg);
93
94void handover_mt_allocate_lchan(struct handover *ho);
95int handover_mt_send_rr_ho_command(struct handover *ho);