sbcap: Request and handle Write Replace Warning Indication

Change-Id: I563e7d1c999f14b8197bb41e85b7bcf6262fe2a0
This commit is contained in:
Pau Espin 2022-07-26 16:36:29 +02:00
parent 1429377005
commit 4a9d22e5a0
7 changed files with 81 additions and 1 deletions

View File

@ -16,6 +16,7 @@ enum cbc_cell_id_type {
CBC_CELL_ID_LAI, CBC_CELL_ID_LAI,
CBC_CELL_ID_LAC, CBC_CELL_ID_LAC,
CBC_CELL_ID_CI, CBC_CELL_ID_CI,
CBC_CELL_ID_ECGI,
}; };
struct cbc_cell_id { struct cbc_cell_id {
@ -27,6 +28,7 @@ struct cbc_cell_id {
struct osmo_location_area_id lai; struct osmo_location_area_id lai;
uint16_t lac; uint16_t lac;
uint16_t ci; uint16_t ci;
struct osmo_eutran_cell_global_id ecgi;
} u; } u;
/* only in failure list */ /* only in failure list */
struct { struct {

View File

@ -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_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_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); 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);

View File

@ -31,6 +31,8 @@ enum smscb_fsm_event {
/* SBc-AP peer confirms delete */ /* SBc-AP peer confirms delete */
SMSCB_E_SBCAP_DELETE_ACK, SMSCB_E_SBCAP_DELETE_ACK,
SMSCB_E_SBCAP_DELETE_NACK, SMSCB_E_SBCAP_DELETE_NACK,
/* SBc-AP peer sends Write Replace Warning Indication to us */
SMSCB_E_SBCAP_WRITE_IND,
}; };
enum smscb_fsm_state { enum smscb_fsm_state {

View File

@ -61,6 +61,10 @@ const char *cbc_cell_id2str(const struct cbc_cell_id *cid)
case CBC_CELL_ID_CI: case CBC_CELL_ID_CI:
snprintf(buf, sizeof(buf), "CI %u", cid->u.ci); snprintf(buf, sizeof(buf), "CI %u", cid->u.ci);
break; 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: default:
snprintf(buf, sizeof(buf), "<invalid>"); snprintf(buf, sizeof(buf), "<invalid>");
break; break;

View File

@ -333,6 +333,8 @@ int cbc_sbcap_link_rx_cb(struct cbc_sbcap_link *link, SBcAP_SBC_AP_PDU_t *pdu)
switch (pdu->present) { switch (pdu->present) {
case SBcAP_SBC_AP_PDU_PR_initiatingMessage: case SBcAP_SBC_AP_PDU_PR_initiatingMessage:
switch (pdu->choice.initiatingMessage.procedureCode) { 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: default:
break; break;
} }

View File

@ -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); 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; 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; 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);
}

View File

@ -62,6 +62,7 @@ const struct value_string smscb_fsm_event_names[] = {
{ SMSCB_E_SBCAP_WRITE_NACK, "SBcAP_WRITE_NACK" }, { SMSCB_E_SBCAP_WRITE_NACK, "SBcAP_WRITE_NACK" },
{ SMSCB_E_SBCAP_DELETE_ACK, "SBcAP_DELETE_ACK" }, { SMSCB_E_SBCAP_DELETE_ACK, "SBcAP_DELETE_ACK" },
{ SMSCB_E_SBCAP_DELETE_NACK, "SBcAP_DELETE_NACK" }, { SMSCB_E_SBCAP_DELETE_NACK, "SBcAP_DELETE_NACK" },
{ SMSCB_E_SBCAP_WRITE_IND, "SBcAP_WRITE_IND" },
{ 0, NULL } { 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); 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 * 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 cbc_message_peer *mp = (struct cbc_message_peer *) fi->priv;
struct osmo_cbsp_decoded *cbsp; struct osmo_cbsp_decoded *cbsp;
SBcAP_SBC_AP_PDU_t *sbcap; SBcAP_SBC_AP_PDU_t *sbcap;
A_SEQUENCE_OF(void) *as_pdu;
SBcAP_Write_Replace_Warning_Indication_IEs_t *ie;
switch (event) { switch (event) {
case SMSCB_E_DELETE: /* send KILL to BSC */ 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); osmo_fsm_inst_state_chg(fi, SMSCB_S_WAIT_DELETE_ACK, 10, T_WAIT_DELETE_ACK);
break; 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: default:
OSMO_ASSERT(0); OSMO_ASSERT(0);
} }
@ -647,7 +693,8 @@ struct osmo_fsm smscb_p_fsm = {
.name = "SMSCB-PEER", .name = "SMSCB-PEER",
.states = smscb_p_fsm_states, .states = smscb_p_fsm_states,
.num_states = ARRAY_SIZE(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, .allstate_action = smscb_p_fsm_allstate,
.timer_cb = smscb_p_fsm_timer_cb, .timer_cb = smscb_p_fsm_timer_cb,
.log_subsys = DCBSP, .log_subsys = DCBSP,