From cab2fb2a28efa99556a4c3a10e1fc0157475d249 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 25 Apr 2022 11:10:30 +0200 Subject: [PATCH] cbsp: Implement KILL for Emergency Broadcast So far, we only implemented KILL for CBS, but not for Emergency broadcasts. This patch adds KILL support for Emergency, by which a CBC can terminate broadcast of a previously-started Emergency message before its scheduled period ends. Change-Id: Ie91939b93de6847eeb5d00c97a137c43721c2711 Closes: OS#5540 Related: SYS#5906 (cherry picked from commit 7a982712ac258c9b0b1df64fba181a7beaefa5f2) --- src/osmo-bsc/smscb.c | 62 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/src/osmo-bsc/smscb.c b/src/osmo-bsc/smscb.c index 208c20353..8ec239a99 100644 --- a/src/osmo-bsc/smscb.c +++ b/src/osmo-bsc/smscb.c @@ -243,6 +243,12 @@ static void append_bcast_compl(struct response_state *r_state, struct gsm_bts *b llist_add_tail(¢->list, &r_state->num_completed.list); } +static bool etws_msg_id_matches(uint16_t a, uint16_t b) +{ + /* ETWS messages are identified by the twelve most significant bits of the Message ID */ + return (a & 0xFFF0) == (b & 0xFFF0); +} + /*! Iterate over all BTSs, find matching ones, execute command on BTS, add result * to succeeded/failed lists. * \param[in] net GSM network in which we operate @@ -665,23 +671,53 @@ static int bts_rx_kill(struct gsm_bts *bts, const struct osmo_cbsp_decoded *dec, struct response_state *r_state, void *priv) { const struct osmo_cbsp_kill *kill = &dec->u.kill; - struct bts_smscb_chan_state *chan_state; - struct bts_smscb_message *smscb; - bool extended = false; - if (kill->channel_ind && *kill->channel_ind == 0x01) - extended = true; - chan_state = bts_get_smscb_chan(bts, extended); + if (kill->channel_ind) { + /* KILL for CBS message */ + struct bts_smscb_chan_state *chan_state; + struct bts_smscb_message *smscb; + bool extended = false; - /* Find message by msg_id + old_serial_nr */ - smscb = bts_find_smscb(chan_state, kill->msg_id, kill->old_serial_nr); - if (!smscb) - return -CBSP_CAUSE_MSG_REF_NOT_IDENTIFIED; + if (*kill->channel_ind == 0x01) + extended = true; - append_bcast_compl(r_state, chan_state->bts, smscb); + chan_state = bts_get_smscb_chan(bts, extended); - /* Remove it */ - bts_smscb_del(smscb, chan_state, "KILL"); + /* Find message by msg_id + old_serial_nr */ + smscb = bts_find_smscb(chan_state, kill->msg_id, kill->old_serial_nr); + if (!smscb) + return -CBSP_CAUSE_MSG_REF_NOT_IDENTIFIED; + + append_bcast_compl(r_state, chan_state->bts, smscb); + + /* Remove it */ + bts_smscb_del(smscb, chan_state, "KILL"); + } else { + /* KILL for Emergency */ + struct bts_etws_state *bes = &bts->etws; + + if (!bes->active) { + LOG_BTS(bts, DCBS, LOGL_NOTICE, "Rx CBSP KILL (Emerg) but no emergency " + "broadcast is currently active in this cell\n"); + return -CBSP_CAUSE_MSG_REF_NOT_IDENTIFIED; + } + + if (kill->msg_id != bes->input.msg_id) { + LOG_BTS(bts, DCBS, LOGL_NOTICE, "Rx CBSP KILL (Emerg) for msg_id 0x%04x, but " + "current emergency msg_id is 0x%04x\n", kill->msg_id, bes->input.msg_id); + return -CBSP_CAUSE_MSG_REF_NOT_IDENTIFIED; + } + + if (!etws_msg_id_matches(kill->old_serial_nr, bes->input.serial_nr)) { + LOG_BTS(bts, DCBS, LOGL_NOTICE, "Rx CBSP KILL (Emerg) for old_serial_nr 0x%04x, but " + "current emergency serial_nr is 0x%04x\n", + kill->old_serial_nr, bes->input.serial_nr); + return -CBSP_CAUSE_MSG_REF_NOT_IDENTIFIED; + } + + /* stop broadcasting the PN in this BTS */ + etws_pn_stop(bts, false); + } return 0; }