aboutsummaryrefslogtreecommitdiffstats
path: root/src/libbsc/handover_logic.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libbsc/handover_logic.c')
-rw-r--r--src/libbsc/handover_logic.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/src/libbsc/handover_logic.c b/src/libbsc/handover_logic.c
index cdc21f56f..ca29290be 100644
--- a/src/libbsc/handover_logic.c
+++ b/src/libbsc/handover_logic.c
@@ -40,6 +40,7 @@
#include <osmocom/bsc/gsm_04_08_utils.h>
#include <osmocom/bsc/handover.h>
#include <osmocom/bsc/handover_cfg.h>
+#include <osmocom/bsc/bsc_subscr_conn_fsm.h>
static LLIST_HEAD(bsc_handovers);
static LLIST_HEAD(handover_decision_callbacks);
@@ -81,6 +82,39 @@ static struct bsc_handover *bsc_ho_by_old_lchan(struct gsm_lchan *old_lchan)
int bsc_handover_start(enum hodec_id from_hodec_id, struct gsm_lchan *old_lchan, struct gsm_bts *new_bts,
enum gsm_chan_t new_lchan_type)
{
+ /*! Note: Due to architectural changes this function now acts as a
+ * wrapper function that dispatches a signal to the GSCON FSM,
+ * which then calls bsc_handover_start_fsm() in case handover is
+ * actually permitted. The FSM will then supervise the handover
+ * process and (if necessary) communicate changes of IP-Addresses
+ * back to the MGW.
+ *
+ * The implementation of a wrapper function had been prefered over
+ * API changes in order to keep code that makes use of
+ * bsc_handover_start() unchanged */
+
+ struct gsm_subscriber_connection *conn;
+
+ OSMO_ASSERT(old_lchan);
+ OSMO_ASSERT(new_bts);
+
+ conn = old_lchan->conn;
+ OSMO_ASSERT(conn);
+
+ conn->user_plane.ho_from_hodec_id = from_hodec_id;
+ conn->user_plane.ho_old_lchan = old_lchan;
+ conn->user_plane.ho_new_bts = new_bts;
+ conn->user_plane.ho_new_lchan_type = new_lchan_type;
+
+ return osmo_fsm_inst_dispatch(conn->fi, GSCON_EV_HO_START, NULL);
+}
+
+/*! \brief Actual implementation of bsc_handover_start(). This function must
+ * not be called directly. The only legal caller is the GSCON FSM in
+ * bsc_subscr_conn_fsm.c. */
+int bsc_handover_start_gscon(struct gsm_lchan *old_lchan, struct gsm_bts *new_bts,
+ enum gsm_chan_t new_lchan_type)
+{
struct gsm_network *network;
struct gsm_lchan *new_lchan;
struct bsc_handover *ho;
@@ -211,6 +245,9 @@ static void ho_T3103_cb(void *_ho)
DEBUGP(DHO, "HO T3103 expired\n");
rate_ctr_inc(&net->bsc_ctrs->ctr[BSC_CTR_HANDOVER_TIMEOUT]);
+ /* Inform the GSCON FSM about the timed out handover */
+ osmo_fsm_inst_dispatch(ho->old_lchan->conn->fi, GSCON_EV_HO_TIMEOUT, NULL);
+
ho->new_lchan->conn->ho_lchan = NULL;
ho->new_lchan->conn = NULL;
lchan_release(ho->new_lchan, 0, RSL_REL_LOCAL_END);
@@ -306,6 +343,9 @@ static int ho_gsm48_ho_compl(struct gsm_lchan *new_lchan)
lchan_release(ho->old_lchan, 0, RSL_REL_LOCAL_END);
handover_free(ho);
+
+ /* Inform the GSCON FSM that the handover is complete */
+ osmo_fsm_inst_dispatch(new_lchan->conn->fi, GSCON_EV_HO_COMPL, NULL);
return 0;
}
@@ -338,7 +378,8 @@ static int ho_gsm48_ho_fail(struct gsm_lchan *old_lchan)
lchan_release(new_lchan, 0, RSL_REL_LOCAL_END);
-
+ /* Inform the GSCON FSM that the handover failed */
+ osmo_fsm_inst_dispatch(old_lchan->conn->fi, GSCON_EV_HO_FAIL, NULL);
return 0;
}