From 4a9d22e5a08bfd5f3820ccf8dc62c7354d434fa6 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Tue, 26 Jul 2022 16:36:29 +0200 Subject: [PATCH] sbcap: Request and handle Write Replace Warning Indication Change-Id: I563e7d1c999f14b8197bb41e85b7bcf6262fe2a0 --- include/osmocom/cbc/cbc_data.h | 2 + include/osmocom/cbc/sbcap_msg.h | 3 ++ include/osmocom/cbc/smscb_message_fsm.h | 2 + src/cbc_data.c | 4 ++ src/sbcap_link_fsm.c | 2 + src/sbcap_msg.c | 20 ++++++++++ src/smscb_peer_fsm.c | 49 ++++++++++++++++++++++++- 7 files changed, 81 insertions(+), 1 deletion(-) diff --git a/include/osmocom/cbc/cbc_data.h b/include/osmocom/cbc/cbc_data.h index 890da67..b857dc2 100644 --- a/include/osmocom/cbc/cbc_data.h +++ b/include/osmocom/cbc/cbc_data.h @@ -16,6 +16,7 @@ enum cbc_cell_id_type { CBC_CELL_ID_LAI, CBC_CELL_ID_LAC, CBC_CELL_ID_CI, + CBC_CELL_ID_ECGI, }; struct cbc_cell_id { @@ -27,6 +28,7 @@ struct cbc_cell_id { struct osmo_location_area_id lai; uint16_t lac; uint16_t ci; + struct osmo_eutran_cell_global_id ecgi; } u; /* only in failure list */ struct { diff --git a/include/osmocom/cbc/sbcap_msg.h b/include/osmocom/cbc/sbcap_msg.h index 286642c..22d043b 100644 --- a/include/osmocom/cbc/sbcap_msg.h +++ b/include/osmocom/cbc/sbcap_msg.h @@ -11,3 +11,6 @@ typedef struct SBcAP_SBC_AP_PDU SBcAP_SBC_AP_PDU_t; SBcAP_SBC_AP_PDU_t *sbcap_gen_write_replace_warning_req(void *ctx, const struct cbc_message *cbcmsg); SBcAP_SBC_AP_PDU_t *sbcap_gen_stop_warning_req(void *ctx, const struct cbc_message *cbcmsg); SBcAP_SBC_AP_PDU_t *sbcap_gen_error_ind(void *ctx, SBcAP_Cause_t cause, SBcAP_SBC_AP_PDU_t *rx_pdu); + + +void cci_from_sbcap_bcast_cell_id(struct cbc_cell_id *cci, const SBcAP_CellId_Broadcast_List_Item_t *it); diff --git a/include/osmocom/cbc/smscb_message_fsm.h b/include/osmocom/cbc/smscb_message_fsm.h index 9636acc..dec719b 100644 --- a/include/osmocom/cbc/smscb_message_fsm.h +++ b/include/osmocom/cbc/smscb_message_fsm.h @@ -31,6 +31,8 @@ enum smscb_fsm_event { /* SBc-AP peer confirms delete */ SMSCB_E_SBCAP_DELETE_ACK, SMSCB_E_SBCAP_DELETE_NACK, + /* SBc-AP peer sends Write Replace Warning Indication to us */ + SMSCB_E_SBCAP_WRITE_IND, }; enum smscb_fsm_state { diff --git a/src/cbc_data.c b/src/cbc_data.c index 68dc024..013b053 100644 --- a/src/cbc_data.c +++ b/src/cbc_data.c @@ -61,6 +61,10 @@ const char *cbc_cell_id2str(const struct cbc_cell_id *cid) case CBC_CELL_ID_CI: snprintf(buf, sizeof(buf), "CI %u", cid->u.ci); break; + case CBC_CELL_ID_ECGI: + snprintf(buf, sizeof(buf), "ECGI %s-%05X-%02X", osmo_plmn_name(&cid->u.ecgi.plmn), + cid->u.ecgi.eci >> 8, cid->u.ecgi.eci & 0xff); + break; default: snprintf(buf, sizeof(buf), ""); break; diff --git a/src/sbcap_link_fsm.c b/src/sbcap_link_fsm.c index 2813611..6a50e91 100644 --- a/src/sbcap_link_fsm.c +++ b/src/sbcap_link_fsm.c @@ -333,6 +333,8 @@ int cbc_sbcap_link_rx_cb(struct cbc_sbcap_link *link, SBcAP_SBC_AP_PDU_t *pdu) switch (pdu->present) { case SBcAP_SBC_AP_PDU_PR_initiatingMessage: switch (pdu->choice.initiatingMessage.procedureCode) { + case SBcAP_ProcedureId_Write_Replace_Warning_Indication: + return osmo_fsm_inst_dispatch(mp->fi, SMSCB_E_SBCAP_WRITE_IND, pdu); default: break; } diff --git a/src/sbcap_msg.c b/src/sbcap_msg.c index bd83045..11a08d1 100644 --- a/src/sbcap_msg.c +++ b/src/sbcap_msg.c @@ -225,6 +225,14 @@ SBcAP_SBC_AP_PDU_t *sbcap_gen_write_replace_warning_req(void *ctx, const struct ASN_SEQUENCE_ADD(as_pdu, ie); } + /* Send Write-Replace-Warning-Indication + * 3GPP TS 36.413 4.3.4.3.5, 3GPP TS 23.041 9.3.39 + * static const long asn_VAL_14_SBcAP_id_Send_Write_Replace_Warning_Indication = 24; */ + ie = sbcap_alloc_Write_Replace_Warning_Request_IE(24, SBcAP_Criticality_ignore, + SBcAP_Write_Replace_Warning_Request_IEs__value_PR_Send_Write_Replace_Warning_Indication); + ie->value.choice.Send_Write_Replace_Warning_Indication = SBcAP_Send_Write_Replace_Warning_Indication_true; + ASN_SEQUENCE_ADD(as_pdu, ie); + return pdu; } @@ -336,3 +344,15 @@ SBcAP_SBC_AP_PDU_t *sbcap_gen_error_ind(void *ctx, SBcAP_Cause_t cause, SBcAP_SB } return pdu; } +static void cci_from_sbcap_ecgi(struct cbc_cell_id *cci, const SBcAP_EUTRAN_CGI_t *eCGI) +{ + cci->id_discr = CBC_CELL_ID_ECGI; + cci->u.ecgi.eci = (osmo_load32be(&eCGI->cell_ID.buf[0]) >> 4); + osmo_plmn_from_bcd(eCGI->pLMNidentity.buf, &cci->u.ecgi.plmn); +} + +/* Fill a cbc_cell_id from a SBcAP_CellId_Broadcast_List_Item */ +void cci_from_sbcap_bcast_cell_id(struct cbc_cell_id *cci, const SBcAP_CellId_Broadcast_List_Item_t *it) +{ + cci_from_sbcap_ecgi(cci, &it->eCGI); +} diff --git a/src/smscb_peer_fsm.c b/src/smscb_peer_fsm.c index f8bc34d..1d87d69 100644 --- a/src/smscb_peer_fsm.c +++ b/src/smscb_peer_fsm.c @@ -62,6 +62,7 @@ const struct value_string smscb_fsm_event_names[] = { { SMSCB_E_SBCAP_WRITE_NACK, "SBcAP_WRITE_NACK" }, { SMSCB_E_SBCAP_DELETE_ACK, "SBcAP_DELETE_ACK" }, { SMSCB_E_SBCAP_DELETE_NACK, "SBcAP_DELETE_NACK" }, + { SMSCB_E_SBCAP_WRITE_IND, "SBcAP_WRITE_IND" }, { 0, NULL } }; @@ -282,6 +283,37 @@ static void cbsp_append_cell_list(struct osmo_cbsp_cell_list *out, void *ctx, out->id_discr = cell_id_from_ccid_discr(id_discr); } +/* append SBcAP cells to msg_peer compl list */ +void msg_peer_append_compl_sbcap_bcast_area_list(struct cbc_message_peer *mp, + const SBcAP_Broadcast_Scheduled_Area_List_t *bcast) +{ + SBcAP_CellId_Broadcast_List_t *cell_id_bscat = bcast->cellId_Broadcast_List; + A_SEQUENCE_OF(struct SBcAP_CellId_Broadcast_List_Item) *as_cell_id_bcast; + SBcAP_CellId_Broadcast_List_Item_t *it; + unsigned int i; + + if (!cell_id_bscat) + return; + + as_cell_id_bcast = (void *) &cell_id_bscat->list; + for (i = 0; i < as_cell_id_bcast->count; i++) { + it = (SBcAP_CellId_Broadcast_List_Item_t *)(as_cell_id_bcast->array[i]); + OSMO_ASSERT(it); + struct cbc_cell_id *cci = NULL; // FIXME: lookup + if (!cci) { + cci = talloc_zero(mp, struct cbc_cell_id); + if (!cci) + return; + llist_add_tail(&cci->list, &mp->num_compl_list); + } + cci_from_sbcap_bcast_cell_id(cci, it); + LOGPFSML(mp->fi, LOGL_DEBUG, "Appending CellId %s to Broadcast Completed list\n", + cbc_cell_id2str(cci)); + cci->num_compl.num_compl += 1; + cci->num_compl.num_bcast_info += 1; + } +} + /*********************************************************************** * actual FSM ***********************************************************************/ @@ -532,6 +564,8 @@ static void smscb_p_fsm_allstate(struct osmo_fsm_inst *fi, uint32_t event, void struct cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv; struct osmo_cbsp_decoded *cbsp; SBcAP_SBC_AP_PDU_t *sbcap; + A_SEQUENCE_OF(void) *as_pdu; + SBcAP_Write_Replace_Warning_Indication_IEs_t *ie; switch (event) { case SMSCB_E_DELETE: /* send KILL to BSC */ @@ -575,6 +609,18 @@ static void smscb_p_fsm_allstate(struct osmo_fsm_inst *fi, uint32_t event, void } osmo_fsm_inst_state_chg(fi, SMSCB_S_WAIT_DELETE_ACK, 10, T_WAIT_DELETE_ACK); break; + case SMSCB_E_SBCAP_WRITE_IND: + sbcap = (SBcAP_SBC_AP_PDU_t *)data; + OSMO_ASSERT(sbcap->present == SBcAP_SBC_AP_PDU_PR_initiatingMessage); + OSMO_ASSERT(sbcap->choice.initiatingMessage.procedureCode == SBcAP_ProcedureId_Write_Replace_Warning_Indication); + as_pdu = (void *)&sbcap->choice.initiatingMessage.value.choice.Write_Replace_Warning_Indication.protocolIEs.list; + /* static const long asn_VAL_36_SBcAP_id_Broadcast_Scheduled_Area_List = 23; */ + ie = sbcap_as_find_ie(as_pdu, 23); + if (!ie) + return; /* IE is optional */ + OSMO_ASSERT(ie->value.present == SBcAP_Write_Replace_Warning_Indication_IEs__value_PR_Broadcast_Scheduled_Area_List); + msg_peer_append_compl_sbcap_bcast_area_list(mp, &ie->value.choice.Broadcast_Scheduled_Area_List); + break; default: OSMO_ASSERT(0); } @@ -647,7 +693,8 @@ struct osmo_fsm smscb_p_fsm = { .name = "SMSCB-PEER", .states = smscb_p_fsm_states, .num_states = ARRAY_SIZE(smscb_p_fsm_states), - .allstate_event_mask = S(SMSCB_E_DELETE), + .allstate_event_mask = S(SMSCB_E_DELETE) | + S(SMSCB_E_SBCAP_WRITE_IND), .allstate_action = smscb_p_fsm_allstate, .timer_cb = smscb_p_fsm_timer_cb, .log_subsys = DCBSP,