Neels Hofmeyr | a2733ae | 2017-11-28 00:29:25 +0100 | [diff] [blame] | 1 | #pragma once |
Holger Hans Peter Freyther | f2553a6 | 2010-06-30 12:58:14 +0800 | [diff] [blame] | 2 | |
Neels Hofmeyr | 45e46d2 | 2018-02-15 14:10:12 +0100 | [diff] [blame] | 3 | #include <stdint.h> |
| 4 | |
| 5 | #include <osmocom/core/linuxlist.h> |
| 6 | #include <osmocom/core/timer.h> |
Harald Welte | 3561bd4 | 2018-01-28 03:04:16 +0100 | [diff] [blame] | 7 | #include <osmocom/gsm/gsm_utils.h> |
Neels Hofmeyr | 31f525e | 2018-05-14 18:14:15 +0200 | [diff] [blame] | 8 | #include <osmocom/gsm/gsm0808.h> |
Neels Hofmeyr | 45e46d2 | 2018-02-15 14:10:12 +0100 | [diff] [blame] | 9 | |
Neels Hofmeyr | 19bed23 | 2018-03-22 04:54:57 +0100 | [diff] [blame] | 10 | #include <osmocom/bsc/neighbor_ident.h> |
Neels Hofmeyr | 31f525e | 2018-05-14 18:14:15 +0200 | [diff] [blame] | 11 | #include <osmocom/bsc/gsm_data.h> |
Neels Hofmeyr | 19bed23 | 2018-03-22 04:54:57 +0100 | [diff] [blame] | 12 | |
Neels Hofmeyr | 31f525e | 2018-05-14 18:14:15 +0200 | [diff] [blame] | 13 | struct gsm_network; |
Neels Hofmeyr | a2733ae | 2017-11-28 00:29:25 +0100 | [diff] [blame] | 14 | struct gsm_lchan; |
| 15 | struct gsm_bts; |
Holger Hans Peter Freyther | f2553a6 | 2010-06-30 12:58:14 +0800 | [diff] [blame] | 16 | struct gsm_subscriber_connection; |
Harald Welte | 3561bd4 | 2018-01-28 03:04:16 +0100 | [diff] [blame] | 17 | struct gsm_meas_rep mr; |
Holger Hans Peter Freyther | f2553a6 | 2010-06-30 12:58:14 +0800 | [diff] [blame] | 18 | |
Neels Hofmeyr | 31f525e | 2018-05-14 18:14:15 +0200 | [diff] [blame] | 19 | enum handover_result { |
| 20 | HO_RESULT_OK, |
| 21 | HO_RESULT_FAIL_NO_CHANNEL, |
| 22 | HO_RESULT_FAIL_RR_HO_FAIL, |
| 23 | HO_RESULT_FAIL_TIMEOUT, |
| 24 | HO_RESULT_CONN_RELEASE, |
| 25 | HO_RESULT_ERROR, |
Neels Hofmeyr | 45e46d2 | 2018-02-15 14:10:12 +0100 | [diff] [blame] | 26 | }; |
| 27 | |
Neels Hofmeyr | 31f525e | 2018-05-14 18:14:15 +0200 | [diff] [blame] | 28 | extern const struct value_string handover_result_names[]; |
| 29 | inline static const char *handover_result_name(enum handover_result val) |
| 30 | { return get_value_string(handover_result_names, val); } |
Neels Hofmeyr | 45e46d2 | 2018-02-15 14:10:12 +0100 | [diff] [blame] | 31 | |
Neels Hofmeyr | 31f525e | 2018-05-14 18:14:15 +0200 | [diff] [blame] | 32 | int bts_handover_count(struct gsm_bts *bts, int ho_scopes); |
Neels Hofmeyr | 45e46d2 | 2018-02-15 14:10:12 +0100 | [diff] [blame] | 33 | |
| 34 | /* Handover decision algorithms' actions to take on incoming handover-relevant events. |
| 35 | * |
| 36 | * All events that are interesting for handover decision are actually communicated by S_LCHAN_* signals, |
| 37 | * so theoretically, each handover algorithm could evaluate those. However, handover_logic.c cleans up |
| 38 | * handover operation state upon receiving some of these signals. To allow a handover decision algorithm |
Neels Hofmeyr | 31f525e | 2018-05-14 18:14:15 +0200 | [diff] [blame] | 39 | * to take advantage of e.g. the struct handover before it is discarded, the handover decision event |
Neels Hofmeyr | 45e46d2 | 2018-02-15 14:10:12 +0100 | [diff] [blame] | 40 | * handler needs to be invoked before handover_logic.c discards the state. For example, if the handover |
| 41 | * decision wants to place a penalty timer upon a handover failure, it still needs to know which target |
| 42 | * cell the handover failed for; handover_logic.c erases that knowledge on handover failure, since it |
| 43 | * needs to clean up the lchan's handover state. |
| 44 | * |
| 45 | * The most explicit and safest way to ensure the correct order of event handling is to invoke the |
| 46 | * handover decision algorithm's actions from handover_logic.c itself, before cleaning up. This struct |
| 47 | * provides the callback functions for this purpose. |
| 48 | * |
| 49 | * For consistency, also handle signals in this way that aren't actually in danger of interference from |
| 50 | * handover_logic.c (which also saves repeated lookup of handover state for lchans). Thus, handover |
| 51 | * decision algorithms should not register any signal handler at all. |
| 52 | */ |
| 53 | struct handover_decision_callbacks { |
| 54 | struct llist_head entry; |
| 55 | |
| 56 | int hodec_id; |
| 57 | |
| 58 | void (*on_measurement_report)(struct gsm_meas_rep *mr); |
Neels Hofmeyr | 31f525e | 2018-05-14 18:14:15 +0200 | [diff] [blame] | 59 | void (*on_handover_end)(struct gsm_subscriber_connection *conn, enum handover_result result); |
Neels Hofmeyr | 45e46d2 | 2018-02-15 14:10:12 +0100 | [diff] [blame] | 60 | }; |
| 61 | |
| 62 | void handover_decision_callbacks_register(struct handover_decision_callbacks *hdc); |
| 63 | struct handover_decision_callbacks *handover_decision_callbacks_get(int hodec_id); |
Neels Hofmeyr | 19bed23 | 2018-03-22 04:54:57 +0100 | [diff] [blame] | 64 | |
Neels Hofmeyr | 31f525e | 2018-05-14 18:14:15 +0200 | [diff] [blame] | 65 | int bsc_tx_bssmap_ho_required(struct gsm_lchan *lchan, const struct gsm0808_cell_id_list2 *target_cells); |
| 66 | int bsc_tx_bssmap_ho_request_ack(struct gsm_subscriber_connection *conn, |
| 67 | struct msgb *rr_ho_command); |
| 68 | int bsc_tx_bssmap_ho_detect(struct gsm_subscriber_connection *conn); |
| 69 | enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection *conn, |
| 70 | struct gsm_lchan *lchan); |
| 71 | void bsc_tx_bssmap_ho_failure(struct gsm_subscriber_connection *conn); |
| 72 | |
Neels Hofmeyr | 19bed23 | 2018-03-22 04:54:57 +0100 | [diff] [blame] | 73 | struct gsm_bts *bts_by_neighbor_ident(const struct gsm_network *net, |
| 74 | const struct neighbor_ident_key *search_for); |
| 75 | struct neighbor_ident_key *bts_ident_key(const struct gsm_bts *bts); |
Neels Hofmeyr | 31f525e | 2018-05-14 18:14:15 +0200 | [diff] [blame] | 76 | |
| 77 | void handover_parse_inter_bsc_mt(struct gsm_subscriber_connection *conn, |
| 78 | struct msgb *ho_request_msg); |
| 79 | |
| 80 | void handover_mt_allocate_lchan(struct handover *ho); |
| 81 | int handover_mt_send_rr_ho_command(struct handover *ho); |