path: root/include
diff options
authorNeels Hofmeyr <neels@hofmeyr.de>2021-03-09 17:10:18 +0100
committerNeels Hofmeyr <neels@hofmeyr.de>2021-03-24 10:02:29 +0100
commitd88f9a538408c69c3a39b5370197aedc8492c3fc (patch)
treeabed300bdb92553a1e503d1b6c6c47d1db55d5ad /include
parent3ac1278dcfba946c67329060341385854ddd31a5 (diff)
refactor handover penalty timers
So far the list of penalty timers was stored for an opaque target pointer. That was either a gsm_bts pointer for a local BTS, or a cell identifier list pointer for a remote-BSS cell. Reasons to refactor penalty timers: - The cell identifier list pointer came from the neighbor configuration storage, but the way cell neighbor config is stored will change in a subsequent patch. There will be no more cell identifier lists there. - Storing object pointers is inherently unsafe -- if an object gets removed and another gets allocated, the penalty timer could theoretically remain in force for an unrelated object. Rather store penalty timers for specific Cell IDs. Since remote-BSS neighbors can be requested by a cell identifier *list*, use a gsm0808_cell_id_list2 as key in the list of penalty timers. Fix handover_test.c: have different CI for each local BTS. So far it was the same LAC+CI for all BTSes, which now would make the test fail, because any penalty timer would appear to apply to all local cells. Related: OS#5018 Change-Id: I72dd6226a6d69c3f653a3174c6f55bf4eecc6885
Diffstat (limited to 'include')
3 files changed, 22 insertions, 33 deletions
diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h
index 0c0e46734..efa413411 100644
--- a/include/osmocom/bsc/bts.h
+++ b/include/osmocom/bsc/bts.h
@@ -622,6 +622,8 @@ char *gsm_bts_name(const struct gsm_bts *bts);
bool gsm_bts_matches_lai(const struct gsm_bts *bts, const struct osmo_location_area_id *lai);
bool gsm_bts_matches_cell_id(const struct gsm_bts *bts, const struct gsm0808_cell_id *cell_id);
+void gsm_bts_cell_id(struct gsm0808_cell_id *cell_id, const struct gsm_bts *bts);
+void gsm_bts_cell_id_list(struct gsm0808_cell_id_list2 *cell_id_list, const struct gsm_bts *bts);
int gsm_bts_local_neighbor_add(struct gsm_bts *bts, struct gsm_bts *neighbor);
int gsm_bts_local_neighbor_del(struct gsm_bts *bts, const struct gsm_bts *neighbor);
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index af1c8e853..1bf21aef1 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -207,6 +207,10 @@ struct handover {
enum gsm_chan_t new_lchan_type;
struct neighbor_ident_key target_cell;
+ /* For inter-BSC handover, this may reflect more than one Cell ID. Must also be set for intra-BSC handover,
+ * because it is used as key for penalty timers (e.g. in handover decision 2). */
+ struct gsm0808_cell_id_list2 target_cell_ids;
uint8_t ho_ref;
struct gsm_bts *new_bts;
struct gsm_lchan *new_lchan;
@@ -248,7 +252,7 @@ struct gsm_subscriber_connection {
struct {
int failures;
- struct penalty_timers *penalty_timers;
+ struct llist_head penalty_timers;
} hodec2;
/* "Codec List (MSC Preferred)" as received by the BSSAP Assignment Request. 3GPP 48.008
diff --git a/include/osmocom/bsc/penalty_timers.h b/include/osmocom/bsc/penalty_timers.h
index f5d17786c..d662b3c31 100644
--- a/include/osmocom/bsc/penalty_timers.h
+++ b/include/osmocom/bsc/penalty_timers.h
@@ -2,40 +2,23 @@
* initially used by handover algorithm 2 to keep per-BTS timers for each subscriber connection. */
#pragma once
-/* Opaque struct to manage penalty timers */
-struct penalty_timers;
+#include <osmocom/gsm/gsm0808_utils.h>
-/* Initialize a list of penalty timers.
- * param ctx: talloc context to allocate in.
- * returns an empty struct penalty_timers. */
-struct penalty_timers *penalty_timers_init(void *ctx);
+struct penalty_timer {
+ struct llist_head entry;
-/* Add a penalty timer for an arbitrary object.
- * Note: the ownership of for_object remains with the caller; it is handled as a mere void* value, so
- * invalid pointers can be handled without problems, while common sense dictates that invalidated
- * pointers (freed objects) should probably be removed from this list. More importantly, the pointer must
- * match any pointers used to query penalty timers, so for_object should reference some global/singleton
- * object that tends to stay around longer than the penalty timers.
- * param pt: penalty timers list as from penalty_timers_init().
- * param for_object: arbitrary pointer reference to store a penalty timer for (passing NULL is possible,
- * but note that penalty_timers_clear() will clear all timers if given for_object=NULL).
- * param timeout: penalty time in seconds. */
-void penalty_timers_add(struct penalty_timers *pt, const void *for_object, int timeout);
+ struct gsm0808_cell_id for_target_cell;
+ unsigned int timeout;
-/* Return the amount of penalty time remaining for an object.
- * param pt: penalty timers list as from penalty_timers_init().
- * param for_object: arbitrary pointer reference to query penalty timers for.
- * returns seconds remaining until all penalty time has expired. */
-unsigned int penalty_timers_remaining(struct penalty_timers *pt, const void *for_object);
+void penalty_timers_add(void *ctx, struct llist_head *penalty_timers,
+ const struct gsm0808_cell_id *for_target_cell, int timeout);
+void penalty_timers_add_list(void *ctx, struct llist_head *penalty_timers,
+ const struct gsm0808_cell_id_list2 *for_target_cells, int timeout);
-/* Clear penalty timers for one or all objects.
- * param pt: penalty timers list as from penalty_timers_init().
- * param for_object: arbitrary pointer reference to clear penalty time for,
- * or NULL to clear all timers. */
-void penalty_timers_clear(struct penalty_timers *pt, const void *for_object);
+unsigned int penalty_timers_remaining(struct llist_head *penalty_timers,
+ const struct gsm0808_cell_id *for_target_cell);
+unsigned int penalty_timers_remaining_list(struct llist_head *penalty_timers,
+ const struct gsm0808_cell_id_list2 *for_target_cells);
-/* Free a struct as returned from penalty_timers_init().
- * Clear all timers from the list, deallocate the list and set the pointer to NULL.
- * param pt: pointer-to-pointer which references a struct penalty_timers as returned by
- * penalty_timers_init(); *pt_p will be set to NULL. */
-void penalty_timers_free(struct penalty_timers **pt_p);
+void penalty_timers_clear(struct llist_head *penalty_timers, const struct gsm0808_cell_id *for_target_cell);