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 7a982712ac)
This commit is contained in:
Harald Welte 2022-04-25 11:10:30 +02:00
parent ac123fd58e
commit cab2fb2a28
1 changed files with 49 additions and 13 deletions

View File

@ -243,6 +243,12 @@ static void append_bcast_compl(struct response_state *r_state, struct gsm_bts *b
llist_add_tail(&cent->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;
}