diff --git a/include/osmocom/cbc/cbc_data.h b/include/osmocom/cbc/cbc_data.h index b857dc2..6d64f04 100644 --- a/include/osmocom/cbc/cbc_data.h +++ b/include/osmocom/cbc/cbc_data.h @@ -17,6 +17,7 @@ enum cbc_cell_id_type { CBC_CELL_ID_LAC, CBC_CELL_ID_CI, CBC_CELL_ID_ECGI, + CBC_CELL_ID_TAI, }; struct cbc_cell_id { @@ -29,6 +30,7 @@ struct cbc_cell_id { uint16_t lac; uint16_t ci; struct osmo_eutran_cell_global_id ecgi; + struct osmo_tracking_area_id tai; } u; /* only in failure list */ struct { diff --git a/include/osmocom/cbc/sbcap_msg.h b/include/osmocom/cbc/sbcap_msg.h index 22d043b..ce76ef3 100644 --- a/include/osmocom/cbc/sbcap_msg.h +++ b/include/osmocom/cbc/sbcap_msg.h @@ -14,3 +14,4 @@ SBcAP_SBC_AP_PDU_t *sbcap_gen_error_ind(void *ctx, SBcAP_Cause_t cause, SBcAP_SB void cci_from_sbcap_bcast_cell_id(struct cbc_cell_id *cci, const SBcAP_CellId_Broadcast_List_Item_t *it); +void cci_from_sbcap_tai(struct cbc_cell_id *cci, const SBcAP_TAI_t *tai); diff --git a/src/cbc_data.c b/src/cbc_data.c index 013b053..3029ffc 100644 --- a/src/cbc_data.c +++ b/src/cbc_data.c @@ -65,6 +65,9 @@ const char *cbc_cell_id2str(const struct cbc_cell_id *cid) 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; + case CBC_CELL_ID_TAI: + snprintf(buf, sizeof(buf), "TAI %s-%u", osmo_plmn_name(&cid->u.tai.plmn), cid->u.tai.tac); + break; default: snprintf(buf, sizeof(buf), ""); break; diff --git a/src/sbcap_msg.c b/src/sbcap_msg.c index 11a08d1..1c0e768 100644 --- a/src/sbcap_msg.c +++ b/src/sbcap_msg.c @@ -356,3 +356,11 @@ void cci_from_sbcap_bcast_cell_id(struct cbc_cell_id *cci, const SBcAP_CellId_Br { cci_from_sbcap_ecgi(cci, &it->eCGI); } + +/* Fill a cbc_cell_id from a SBcAP_TAI_t */ +void cci_from_sbcap_tai(struct cbc_cell_id *cci, const SBcAP_TAI_t *tai) +{ + cci->id_discr = CBC_CELL_ID_TAI; + cci->u.tai.tac = osmo_load16be(tai->tAC.buf); + osmo_plmn_from_bcd(tai->pLMNidentity.buf, &cci->u.tai.plmn); +} diff --git a/src/smscb_peer_fsm.c b/src/smscb_peer_fsm.c index 1d87d69..2c1edab 100644 --- a/src/smscb_peer_fsm.c +++ b/src/smscb_peer_fsm.c @@ -314,6 +314,31 @@ void msg_peer_append_compl_sbcap_bcast_area_list(struct cbc_message_peer *mp, } } +/* append SBcAP cells to msg_peer fail list */ +void msg_peer_append_fail_sbcap_tai_list(struct cbc_message_peer *mp, + const SBcAP_List_of_TAIs_t *tais) +{ + A_SEQUENCE_OF(List_of_TAIs__Member) *as_tais = (void *)&tais->list; + List_of_TAIs__Member *it; + unsigned int i; + + for (i = 0; i < as_tais->count; i++) { + it = (List_of_TAIs__Member *)(as_tais->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->fail_list); + } + cci_from_sbcap_tai(cci, &it->tai); + cci->fail.cause = SBcAP_Cause_tracking_area_not_valid; + LOGPFSML(mp->fi, LOGL_DEBUG, "Appending CellId %s (cause: %s) to Failed list\n", + cbc_cell_id2str(cci), sbcap_cause_str(cci->fail.cause)); + } +} + /*********************************************************************** * actual FSM ***********************************************************************/ @@ -342,7 +367,9 @@ static void smscb_p_fsm_wait_write_ack(struct osmo_fsm_inst *fi, uint32_t event, { struct cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv; struct osmo_cbsp_decoded *dec = NULL; - //SBcAP_SBC_AP_PDU_t *pdu = NULL; + SBcAP_SBC_AP_PDU_t *sbcap = NULL; + A_SEQUENCE_OF(void) *as_pdu; + SBcAP_Write_Replace_Warning_Response_IEs_t *ie; switch (event) { case SMSCB_E_CBSP_WRITE_ACK: @@ -363,13 +390,21 @@ static void smscb_p_fsm_wait_write_ack(struct osmo_fsm_inst *fi, uint32_t event, osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_E_CBSP_WRITE_NACK, mp); break; case SMSCB_E_SBCAP_WRITE_ACK: - //pdu = data; + sbcap = data; + OSMO_ASSERT(sbcap->present == SBcAP_SBC_AP_PDU_PR_successfulOutcome); + OSMO_ASSERT(sbcap->choice.successfulOutcome.procedureCode == SBcAP_ProcedureId_Write_Replace_Warning); + as_pdu = (void *)&sbcap->choice.successfulOutcome.value.choice.Write_Replace_Warning_Response.protocolIEs.list; + /* static const long asn_VAL_21_SBcAP_id_Unknown_Tracking_Area_List = 22; */ + ie = sbcap_as_find_ie(as_pdu, 22); + if (ie) { /* IE is optional */ + OSMO_ASSERT(ie->value.present == SBcAP_Write_Replace_Warning_Response_IEs__value_PR_List_of_TAIs); + msg_peer_append_fail_sbcap_tai_list(mp, &ie->value.choice.List_of_TAIs); + } osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0); /* Signal parent fsm about completion */ osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_E_SBCAP_WRITE_ACK, mp); break; case SMSCB_E_SBCAP_WRITE_NACK: - //pdu = data; osmo_fsm_inst_state_chg(fi, SMSCB_S_ACTIVE, 0, 0); /* Signal parent fsm about completion */ osmo_fsm_inst_dispatch(fi->proc.parent, SMSCB_E_SBCAP_WRITE_NACK, mp);