From 2a77f1780f14e9393be37f6619fb00c559d6a1d0 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Mon, 13 Jun 2022 19:14:32 +0200 Subject: [PATCH] smscb: Base cell operational life cycle on CBCH being operative This allows running CBCH/ETWS related procedures only when the CBCH towards MS under that cell is operative. This also allows providing awarness of per-cell status to the CBSP peer as required per specs. Related: SYS#5910 Change-Id: Ia93919be94132fc010acb5bbfef0a6fd51c42981 --- include/osmocom/bsc/smscb.h | 4 +- src/osmo-bsc/bts.c | 11 ++---- src/osmo-bsc/cbch_scheduler.c | 3 +- src/osmo-bsc/osmo_bsc_main.c | 11 +----- src/osmo-bsc/smscb.c | 73 ++++++++++++++++++++++++++++++++++- 5 files changed, 80 insertions(+), 22 deletions(-) diff --git a/include/osmocom/bsc/smscb.h b/include/osmocom/bsc/smscb.h index 03c3bb09e..b4f2e196f 100644 --- a/include/osmocom/bsc/smscb.h +++ b/include/osmocom/bsc/smscb.h @@ -9,6 +9,7 @@ struct bsc_cbc_link; /* smscb.c */ +void smscb_global_init(void); void bts_smscb_del(struct bts_smscb_message *smscb, struct bts_smscb_chan_state *cstate, const char *reason); const char *bts_smscb_msg2str(const struct bts_smscb_message *smscb); @@ -25,7 +26,9 @@ struct bts_smscb_page *bts_smscb_pull_page(struct bts_smscb_chan_state *cstate); void bts_smscb_page_done(struct bts_smscb_chan_state *cstate, struct bts_smscb_page *page); int bts_smscb_rx_cbch_load_ind(struct gsm_bts *bts, bool cbch_extended, bool is_overflow, uint8_t slot_count); +void bts_cbch_init(struct gsm_bts *bts); void bts_cbch_timer_schedule(struct gsm_bts *bts); +void bts_cbch_timer_cb(void *data); enum bsc_cbc_link_mode { BSC_CBC_LINK_MODE_DISABLED = 0, @@ -64,7 +67,6 @@ int bsc_cbc_link_restart(void); int cbsp_tx_decoded(struct bsc_cbc_link *cbc, struct osmo_cbsp_decoded *decoded); void bts_etws_init(struct gsm_bts *bts); -void bts_etws_bootstrap(struct gsm_bts *bts); /* smscb_vty.c: */ void smscb_vty_init(void); diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c index 89895ca3b..4f8a3e1de 100644 --- a/src/osmo-bsc/bts.c +++ b/src/osmo-bsc/bts.c @@ -93,12 +93,6 @@ const char *btstype2str(enum gsm_bts_type type) return get_value_string(bts_type_names, type); } -static void bts_init_cbch_state(struct bts_smscb_chan_state *cstate, struct gsm_bts *bts) -{ - cstate->bts = bts; - INIT_LLIST_HEAD(&cstate->messages); -} - static LLIST_HEAD(bts_models); struct gsm_bts_model *bts_model_find(enum gsm_bts_type type) @@ -152,6 +146,8 @@ static int gsm_bts_talloc_destructor(struct gsm_bts *bts) { paging_destructor(bts); + osmo_timer_del(&bts->cbch_timer); + bts->site_mgr->bts[0] = NULL; if (bts->gprs.cell.mo.fi) { @@ -429,8 +425,7 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, struct gsm_bts_sm *bts_sm memcpy(&bts->mr_half.bts_mode[0], &amr_hr_ms_bts_mode[0], sizeof(amr_hr_ms_bts_mode)); bts->mr_half.num_modes = ARRAY_SIZE(amr_hr_ms_bts_mode); - bts_init_cbch_state(&bts->cbch_basic, bts); - bts_init_cbch_state(&bts->cbch_extended, bts); + bts_cbch_init(bts); bts_etws_init(bts); acc_mgr_init(&bts->acc_mgr, bts); diff --git a/src/osmo-bsc/cbch_scheduler.c b/src/osmo-bsc/cbch_scheduler.c index c66f7431b..d699e7ede 100644 --- a/src/osmo-bsc/cbch_scheduler.c +++ b/src/osmo-bsc/cbch_scheduler.c @@ -246,7 +246,7 @@ static void bts_cbch_send_one(struct bts_smscb_chan_state *cstate) bts_smscb_page_done(cstate, page); } -static void bts_cbch_timer_cb(void *data) +void bts_cbch_timer_cb(void *data) { struct gsm_bts *bts = (struct gsm_bts *)data; @@ -259,7 +259,6 @@ static void bts_cbch_timer_cb(void *data) /* There is one SMSCB message (page) per eight 51-multiframes, i.e. 1.882 seconds */ void bts_cbch_timer_schedule(struct gsm_bts *bts) { - osmo_timer_setup(&bts->cbch_timer, &bts_cbch_timer_cb, bts); osmo_timer_schedule(&bts->cbch_timer, 1, 882920); } diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c index f6da74a81..920693f6c 100644 --- a/src/osmo-bsc/osmo_bsc_main.c +++ b/src/osmo-bsc/osmo_bsc_main.c @@ -359,14 +359,6 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx) osmo_fsm_inst_dispatch(ts->fi, TS_EV_RSL_READY, NULL); } - /* Start CBCH transmit timer if CBCH is present */ - if (trx->nr == 0 && gsm_bts_get_cbch(trx->bts)) - bts_cbch_timer_schedule(trx->bts); - - /* Start ETWS/PWS Primary Notification, if active */ - if (trx->nr == 0) - bts_etws_bootstrap(trx->bts); - /* Drop all expired channel requests in the list */ abis_rsl_chan_rqd_queue_flush(trx->bts); } @@ -469,8 +461,6 @@ static int inp_sig_cb(unsigned int subsys, unsigned int signal, rate_ctr_inc(rate_ctr_group_get_ctr(trx->bts->bts_ctrs, BTS_CTR_BTS_RSL_FAIL)); acc_ramp_abort(&trx->bts->acc_ramp); gsm_trx_all_ts_dispatch(trx, TS_EV_RSL_DOWN, NULL); - if (trx->nr == 0) - osmo_timer_del(&trx->bts->cbch_timer); } gsm_bts_sm_mo_reset(trx->bts->site_mgr); @@ -935,6 +925,7 @@ int main(int argc, char **argv) lb_init(); acc_ramp_global_init(); paging_global_init(); + smscb_global_init(); /* Read the config */ rc = bsc_network_configure(config_file); diff --git a/src/osmo-bsc/smscb.c b/src/osmo-bsc/smscb.c index 193dc4e97..750770375 100644 --- a/src/osmo-bsc/smscb.c +++ b/src/osmo-bsc/smscb.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,7 @@ #include #include #include +#include /********************************************************************************* * Helper Functions @@ -74,6 +76,19 @@ static int gen_etws_primary_notification(uint8_t *out, uint16_t serial_nr, uint1 return ETWS_PRIM_NOTIF_SIZE; } +static void bts_cbch_init_state(struct bts_smscb_chan_state *cstate, struct gsm_bts *bts) +{ + cstate->bts = bts; + INIT_LLIST_HEAD(&cstate->messages); +} + +void bts_cbch_init(struct gsm_bts *bts) +{ + bts_cbch_init_state(&bts->cbch_basic, bts); + bts_cbch_init_state(&bts->cbch_extended, bts); + osmo_timer_setup(&bts->cbch_timer, &bts_cbch_timer_cb, bts); +} + /*! Obtain SMSCB Channel State for given BTS (basic or extended CBCH) */ struct bts_smscb_chan_state *bts_get_smscb_chan(struct gsm_bts *bts, bool extended) { @@ -1033,8 +1048,64 @@ void bts_etws_init(struct gsm_bts *bts) } /* BSC is bootstrapping a BTS; install any currently active ETWS PN */ -void bts_etws_bootstrap(struct gsm_bts *bts) +static void bts_etws_bootstrap(struct gsm_bts *bts) { if (bts->etws.active) bts_send_etws(bts); } + +/* Callback function to be called every time we receive a signal from NM */ +static int nm_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct nm_running_chg_signal_data *nsd; + struct gsm_bts *bts; + struct gsm_bts_trx *trx; + + if (signal != S_NM_RUNNING_CHG) + return 0; + + nsd = signal_data; + bts = nsd->bts; + + switch (nsd->obj_class) { + case NM_OC_RADIO_CARRIER: + trx = (struct gsm_bts_trx *)nsd->obj; + break; + case NM_OC_BASEB_TRANSC: + trx = gsm_bts_bb_trx_get_trx((struct gsm_bts_bb_trx *)nsd->obj); + break; + default: + return 0; + } + + struct gsm_lchan *cbch = gsm_bts_get_cbch(bts); + if (!cbch) + return 0; + /* We only care about state changes of TRX holding the CBCH. */ + if (trx != cbch->ts->trx) + return 0; + + if (nsd->running) { + if (trx_is_usable(trx)) { + LOG_BTS(bts, DCBS, LOGL_INFO, "BTS becomes available for CBCH\n"); + /* Start CBCH transmit timer if CBCH is present */ + bts_cbch_timer_schedule(trx->bts); + /* Start ETWS/PWS Primary Notification, if active */ + bts_etws_bootstrap(trx->bts); + } + } else { + if (osmo_timer_pending(&bts->cbch_timer)) { + /* If timer is ongoing it means CBCH was available */ + LOG_BTS(bts, DCBS, LOGL_INFO, "BTS becomes unavailable for CBCH\n"); + osmo_timer_del(&bts->cbch_timer); + } /* else: CBCH was already unavailable before */ + } + return 0; +} + +/* To be called once at startup of the process: */ +void smscb_global_init(void) +{ + osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL); +}