laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/28016 )
Change subject: smscb: Store ETWS input state from CBSP ......................................................................
smscb: Store ETWS input state from CBSP
Only if we store data like the CBSP message_id and serial_number we are able to later (in a subsequent patch) match a CBSP KILL for ETWS/PWS and stop emergency broadcast.
Change-Id: Ide74638880d7e3c6a7c774bf6320d3dce4b11c74 Related: OS#5540 (cherry picked from commit 484f535c5091e3ca62547f8bbb6e06844c2ce8ae) --- M include/osmocom/bsc/bts.h M include/osmocom/bsc/gsm_data.h M include/osmocom/bsc/smscb.h M src/osmo-bsc/bts.c M src/osmo-bsc/smscb.c 5 files changed, 73 insertions(+), 15 deletions(-)
Approvals: laforge: Looks good to me, approved Jenkins Builder: Verified
diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h index cd0f8cb..d3c2ba7 100644 --- a/include/osmocom/bsc/bts.h +++ b/include/osmocom/bsc/bts.h @@ -586,7 +586,7 @@ struct osmo_timer_list cbch_timer; struct bts_smscb_chan_state cbch_basic; struct bts_smscb_chan_state cbch_extended; - struct osmo_timer_list etws_timer; /* when to stop ETWS PN */ + struct bts_etws_state etws;
struct llist_head oml_fail_rep; struct llist_head chan_rqd_queue; diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index 4a58c2b..b69ebf4 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -1106,6 +1106,27 @@ uint8_t overflow; };
+#define ETWS_PRIM_NOTIF_SIZE 56 +#define ETWS_SEC_INFO_SIZE (ETWS_PRIM_NOTIF_SIZE - sizeof(struct gsm341_etws_message)) + +/* per-BTS ETWS/PWS (Emergency) state */ +struct bts_etws_state { + /* are we actively broadcasting emergency in this cell? */ + bool active; + /* input parameters received from CBC */ + struct { + uint16_t msg_id; + uint16_t serial_nr; + uint16_t warn_type; + uint8_t *sec_info; + } input; + /* encoded ETWS primary notification */ + uint8_t primary[ETWS_PRIM_NOTIF_SIZE]; + + /* timer running for the duration of the ETWS Primary Notification (PN) */ + struct osmo_timer_list timer; +}; + struct bts_oml_fail_rep { struct llist_head list; time_t time; diff --git a/include/osmocom/bsc/smscb.h b/include/osmocom/bsc/smscb.h index f48c1a1..5b0905b 100644 --- a/include/osmocom/bsc/smscb.h +++ b/include/osmocom/bsc/smscb.h @@ -64,3 +64,5 @@ void cbc_vty_init(void); 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); diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c index 843d711..1024cfe 100644 --- a/src/osmo-bsc/bts.c +++ b/src/osmo-bsc/bts.c @@ -24,6 +24,7 @@ #include <osmocom/bsc/bts.h> #include <osmocom/bsc/debug.h> #include <osmocom/bsc/nm_common_fsm.h> +#include <osmocom/bsc/smscb.h>
const struct value_string bts_attribute_names[] = { OSMO_VALUE_STRING(BTS_TYPE_VARIANT), @@ -393,6 +394,7 @@
bts_init_cbch_state(&bts->cbch_basic, bts); bts_init_cbch_state(&bts->cbch_extended, bts); + bts_etws_init(bts);
acc_mgr_init(&bts->acc_mgr, bts); acc_ramp_init(&bts->acc_ramp, bts); diff --git a/src/osmo-bsc/smscb.c b/src/osmo-bsc/smscb.c index c89bedb..fc347eb 100644 --- a/src/osmo-bsc/smscb.c +++ b/src/osmo-bsc/smscb.c @@ -59,8 +59,6 @@ INIT_LLIST_HEAD(old); }
-#define ETWS_PRIM_NOTIF_SIZE 56 - /* Build a ETWS Primary Notification message as per TS 23.041 9.4.1.3 */ static int gen_etws_primary_notification(uint8_t *out, uint16_t serial_nr, uint16_t msg_id, uint16_t warn_type, const uint8_t *sec_info) @@ -471,24 +469,52 @@ * Per-BTS Processing of CBSP from CBC, called via cbsp_per_bts() *********************************************************************************/
+static void etws_pn_stop(struct gsm_bts *bts, bool timeout) +{ + if (osmo_bts_has_feature(&bts->features, BTS_FEAT_ETWS_PN)) { + LOG_BTS(bts, DCBS, LOGL_NOTICE, "ETWS PN broadcast via PCH disabled (cause=%s)\n", + timeout ? "timeout" : "request"); + rsl_etws_pn_command(bts, RSL_CHAN_PCH_AGCH, NULL, 0); + } + bts->etws.active = false; + if (!timeout) + osmo_timer_del(&bts->etws.timer); +} + /* timer call-back once ETWS warning period has expired */ static void etws_pn_cb(void *data) { struct gsm_bts *bts = (struct gsm_bts *)data; - LOG_BTS(bts, DCBS, LOGL_NOTICE, "ETWS PN Timeout; disabling broadcast via PCH\n"); - rsl_etws_pn_command(bts, RSL_CHAN_PCH_AGCH, NULL, 0); + etws_pn_stop(bts, true); }
static void etws_primary_to_bts(struct gsm_bts *bts, const struct osmo_cbsp_write_replace *wrepl) { - uint8_t etws_primary[ETWS_PRIM_NOTIF_SIZE]; + struct bts_etws_state *bes = &bts->etws; struct gsm_bts_trx *trx; unsigned int count = 0; int i, j;
- gen_etws_primary_notification(etws_primary, wrepl->new_serial_nr, wrepl->msg_id, - wrepl->u.emergency.warning_type, - wrepl->u.emergency.warning_sec_info); + if (bes->input.sec_info) { + talloc_free(bes->input.sec_info); + bes->input.sec_info = NULL; + } + + /* copy over all the data to per-BTS private state */ + bes->input.msg_id = wrepl->msg_id; + bes->input.serial_nr = wrepl->new_serial_nr; + bes->input.warn_type = wrepl->u.emergency.warning_type; + if (wrepl->u.emergency.warning_sec_info) { + bes->input.sec_info = talloc_named_const(bts, ETWS_SEC_INFO_SIZE, "etws_sec_info"); + if (bes->input.sec_info) + memcpy(bes->input.sec_info, wrepl->u.emergency.warning_sec_info, ETWS_SEC_INFO_SIZE); + } + + /* generate the encoded ETWS PN */ + gen_etws_primary_notification(bes->primary, bes->input.serial_nr, bes->input.msg_id, + bes->input.warn_type, bes->input.sec_info); + + bes->active = true;
/* iterate over all lchan in each TS in each TRX of this BTS */ llist_for_each_entry(trx, &bts->trx_list, list) { @@ -498,8 +524,8 @@ struct gsm_lchan *lchan = &ts->lchan[j]; if (!lchan_may_receive_data(lchan)) continue; - gsm48_send_rr_app_info(lchan, 0x1, 0x0, etws_primary, - sizeof(etws_primary)); + gsm48_send_rr_app_info(lchan, 0x1, 0x0, bes->primary, + sizeof(bes->primary)); count++; } } @@ -510,11 +536,10 @@
/* Notify BTS of primary ETWS notification via vendor-specific Abis message */ if (osmo_bts_has_feature(&bts->features, BTS_FEAT_ETWS_PN)) { - rsl_etws_pn_command(bts, RSL_CHAN_PCH_AGCH, etws_primary, sizeof(etws_primary)); + rsl_etws_pn_command(bts, RSL_CHAN_PCH_AGCH, bes->primary, sizeof(bes->primary)); LOG_BTS(bts, DCBS, LOGL_NOTICE, "Sent ETWS Primary Notification via common channel\n"); if (wrepl->u.emergency.warning_period != 0xffffffff) { - osmo_timer_setup(&bts->etws_timer, etws_pn_cb, bts); - osmo_timer_schedule(&bts->etws_timer, wrepl->u.emergency.warning_period, 0); + osmo_timer_schedule(&bts->etws.timer, wrepl->u.emergency.warning_period, 0); } else LOG_BTS(bts, DCBS, LOGL_NOTICE, "Unlimited ETWS PN broadcast, this breaks " "normal network operation due to PCH blockage\n"); @@ -676,7 +701,7 @@ llist_for_each_entry_safe(smscb, smscb2, &chan_state->messages, list) bts_smscb_del(smscb, chan_state, "RESET");
- osmo_timer_del(&bts->etws_timer); + osmo_timer_del(&bts->etws.timer);
/* Make sure that broadcast is disabled */ rsl_etws_pn_command(bts, RSL_CHAN_PCH_AGCH, NULL, 0); @@ -991,3 +1016,11 @@ { install_element_ve(&bts_show_cbs_cmd); } + + +/* initialize the ETWS state of a BTS */ +void bts_etws_init(struct gsm_bts *bts) +{ + bts->etws.active = false; + osmo_timer_setup(&bts->etws.timer, etws_pn_cb, bts); +}