diff --git a/include/osmocom/hnodeb/hnb_shutdown_fsm.h b/include/osmocom/hnodeb/hnb_shutdown_fsm.h index 69f9f4b..5b40551 100644 --- a/include/osmocom/hnodeb/hnb_shutdown_fsm.h +++ b/include/osmocom/hnodeb/hnb_shutdown_fsm.h @@ -28,6 +28,7 @@ enum hnb_shutdown_fsm_states { HNB_SHUTDOWN_ST_NONE, + HNB_SHUTDOWN_ST_IN_PROGRESS, HNB_SHUTDOWN_ST_EXIT, }; diff --git a/include/osmocom/hnodeb/llsk.h b/include/osmocom/hnodeb/llsk.h index 6a2686a..2c06f3e 100644 --- a/include/osmocom/hnodeb/llsk.h +++ b/include/osmocom/hnodeb/llsk.h @@ -34,6 +34,7 @@ void hnb_llsk_free(struct hnb *hnb); int hnb_llsk_start_listen(struct hnb *hnb); bool hnb_llsk_connected(const struct hnb *hnb); bool hnb_llsk_can_be_configured(struct hnb *hnb); +void hnb_llsk_close_conn(const struct hnb *hnb); int ll_addr_type2af(enum u_addr_type t); int ll_addr2osa(enum u_addr_type t, const union u_addr *uaddr, uint16_t port, struct osmo_sockaddr *osa); diff --git a/src/osmo-hnodeb/hnb_shutdown_fsm.c b/src/osmo-hnodeb/hnb_shutdown_fsm.c index c97a124..7b04c6b 100644 --- a/src/osmo-hnodeb/hnb_shutdown_fsm.c +++ b/src/osmo-hnodeb/hnb_shutdown_fsm.c @@ -43,26 +43,34 @@ static void st_none_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) } static void st_none(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case HNB_SHUTDOWN_EV_START: + hnb_shutdown_fsm_state_chg(fi, HNB_SHUTDOWN_ST_IN_PROGRESS); + break; + } +} + +static void st_in_progress_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) { struct hnb *hnb = (struct hnb *)fi->priv; struct hnb_ue *ue, *ue_tmp; - switch (event) { - case HNB_SHUTDOWN_EV_START: - /* TODO: here we may want to communicate to lower layers over UDsocket that we are shutting down... - * TODO: Also, if Iuh link is still up, maybe send a Hnb deregister req towards HNBGW - */ + /* TODO: Also, if Iuh link is still up, maybe send a Hnb deregister req towards HNBGW */ - /* Drop active UE contexts, together with their GTP/AUDIO sessions: */ - llist_for_each_entry_safe(ue, ue_tmp, &hnb->ue_list, list) - hnb_ue_free(ue); + /* Drop active UE contexts, together with their GTP/AUDIO sessions: */ + llist_for_each_entry_safe(ue, ue_tmp, &hnb->ue_list, list) + hnb_ue_free(ue); - if (osmo_stream_cli_is_connected(hnb->iuh.client)) - osmo_stream_cli_close(hnb->iuh.client); + if (osmo_stream_cli_is_connected(hnb->iuh.client)) + osmo_stream_cli_close(hnb->iuh.client); - hnb_shutdown_fsm_state_chg(fi, HNB_SHUTDOWN_ST_EXIT); - break; - } + /* Close LLSK to notify lower layers that we are shutting down + * even if we are not exiting the process. */ + if (hnb_llsk_connected(hnb)) + hnb_llsk_close_conn(hnb); + + hnb_shutdown_fsm_state_chg(fi, HNB_SHUTDOWN_ST_EXIT); } static void st_exit_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state) @@ -82,11 +90,17 @@ static struct osmo_fsm_state hnb_shutdown_fsm_states[] = { .in_event_mask = X(HNB_SHUTDOWN_EV_START), .out_state_mask = - X(HNB_SHUTDOWN_ST_EXIT), + X(HNB_SHUTDOWN_ST_IN_PROGRESS), .name = "NONE", .onenter = st_none_on_enter, .action = st_none, }, + [HNB_SHUTDOWN_ST_IN_PROGRESS] = { + .out_state_mask = + X(HNB_SHUTDOWN_ST_EXIT), + .name = "IN_PROGRESS", + .onenter = st_in_progress_on_enter, + }, [HNB_SHUTDOWN_ST_EXIT] = { .name = "EXIT", .out_state_mask = diff --git a/src/osmo-hnodeb/llsk.c b/src/osmo-hnodeb/llsk.c index 7e25176..1a1b3c7 100644 --- a/src/osmo-hnodeb/llsk.c +++ b/src/osmo-hnodeb/llsk.c @@ -113,7 +113,12 @@ static int llsk_closed_cb(struct osmo_prim_srv *srv) hnb->llsk.srv = NULL; hnb->llsk.valid_sapi_mask = 0x0; osmo_timer_del(&hnb->llsk.defer_configure_ind_timer); - hnb_shutdown(hnb, "LLSK conn dropped", false); + + /* We actively close the llsk conn during hnb_shutdown, no need to + * re-enter shutdown procedure thin that case: */ + if (!hnb_shutdown_in_progress(hnb)) + hnb_shutdown(hnb, "LLSK conn dropped", false); + return 0; } @@ -136,6 +141,14 @@ bool hnb_llsk_can_be_configured(struct hnb *hnb) return false; } +void hnb_llsk_close_conn(const struct hnb *hnb) +{ + if (!hnb_llsk_connected(hnb)) + return; + osmo_prim_srv_close(hnb->llsk.srv); + /* pointer NULLed in llsk_closed_cb() */ +} + static void llsk_defer_configure_ind_timer_cb(void *data) { struct hnb *hnb = (struct hnb *)data;