nacc: Implement Pkt Cell Change Continue retransmission
Use the fact that the MS must answer the RRBP of the Pkt Cell Change
Continue with a CTRL ACK to find out whether the message was received
successfuly or a retransmission is potentially required.
3GPP TS 44.060:
"""
When the mobile station receives the PACKET CELL CHANGE ORDER or
the PACKET CELL CHANGE CONTINUE message the mobile station shall
transmit a PACKET CONTROL ACKNOWLEDGMENT message in the specified
uplink radio block if a valid RRBP field is received as part of the
message; the mobile station may then switch to a new cell.
"""
Related: SYS#4909
Change-Id: I7cc28922e71699598da0ef6eb90136a47d3c002f
diff --git a/src/nacc_fsm.c b/src/nacc_fsm.c
index d160404..b479f9c 100644
--- a/src/nacc_fsm.c
+++ b/src/nacc_fsm.c
@@ -46,6 +46,7 @@
[NACC_ST_WAIT_REQUEST_SI] = { .T = PCU_TDEF_SI_RESOLVE_TO },
[NACC_ST_TX_NEIGHBOUR_DATA] = {},
[NACC_ST_TX_CELL_CHG_CONTINUE] = {},
+ [NACC_ST_WAIT_CELL_CHG_CONTINUE_ACK] = {}, /* Timeout through event controlled by tbf::poll_timeout() */
[NACC_ST_DONE] = {},
};
@@ -64,6 +65,8 @@
{ NACC_EV_RX_RAC_CI, "RX_RAC_CI" },
{ NACC_EV_RX_SI, "RX_SI" },
{ NACC_EV_CREATE_RLCMAC_MSG, "CREATE_RLCMAC_MSG" },
+ { NACC_EV_RX_CELL_CHG_CONTINUE_ACK, "RX_CELL_CHG_CONTINUE_ACK"},
+ { NACC_EV_TIMEOUT_CELL_CHG_CONTINUE, "TIMEOUT_CELL_CHG_CONTINUE" },
{ 0, NULL }
};
@@ -156,12 +159,21 @@
/* TS 44 060 11.2.2a Packet Cell Change Continue */
static struct msgb *create_packet_cell_chg_continue(const struct nacc_fsm_ctx *ctx,
- const struct gprs_rlcmac_tbf *tbf)
+ const struct nacc_ev_create_rlcmac_msg_ctx *data,
+ uint32_t *new_poll_fn)
{
struct msgb *msg;
int rc;
RlcMacDownlink_t *mac_control_block;
+ struct gprs_rlcmac_tbf *tbf = data->tbf;
struct GprsMs *ms = tbf_ms(tbf);
+ unsigned int rrbp;
+
+ rc = tbf_check_polling(tbf, data->fn, data->ts, new_poll_fn, &rrbp);
+ if (rc < 0) {
+ LOGP(DTBF, LOGL_ERROR, "Failed registering poll for Pkt Cell Chg Continue (%d)\n", rc);
+ return NULL;
+ }
msg = msgb_alloc(GSM_MACBLOCK_LEN, "pkt_cell_chg_continue");
if (!msg)
@@ -180,7 +192,7 @@
uint8_t tfi_is_dl = tbf_direction(tbf) == GPRS_RLCMAC_DL_TBF;
uint8_t tfi = tbf_tfi(tbf);
uint8_t container_id = 0;
- write_packet_cell_change_continue(mac_control_block, tfi_is_dl, tfi, true,
+ write_packet_cell_change_continue(mac_control_block, 1, rrbp, tfi_is_dl, tfi, true,
ctx->neigh_key.tgt_arfcn, ctx->neigh_key.tgt_bsic, container_id);
LOGP(DNACC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Cell Change Continue +++++++++++++++++++++++++\n");
rc = encode_gsm_rlcmac_downlink(&bv, mac_control_block);
@@ -191,6 +203,7 @@
LOGP(DNACC, LOGL_DEBUG, "------------------------- TX : Packet Cell Change Continue -------------------------\n");
rate_ctr_inc(&bts_rate_counters(ms->bts)->ctr[CTR_PKT_CELL_CHG_CONTINUE]);
talloc_free(mac_control_block);
+ tbf_set_polling(tbf, *new_poll_fn, data->ts, GPRS_RLCMAC_POLL_CELL_CHG_CONTINUE);
return msg;
free_ret:
@@ -458,7 +471,24 @@
switch (event) {
case NACC_EV_CREATE_RLCMAC_MSG:
data_ctx = (struct nacc_ev_create_rlcmac_msg_ctx *)data;
- data_ctx->msg = create_packet_cell_chg_continue(ctx, data_ctx->tbf);
+ data_ctx->msg = create_packet_cell_chg_continue(ctx, data_ctx, &ctx->continue_poll_fn);
+ if (data_ctx->msg) {
+ ctx->continue_poll_ts = data_ctx->ts;
+ nacc_fsm_state_chg(fi, NACC_ST_WAIT_CELL_CHG_CONTINUE_ACK);
+ }
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static void st_wait_cell_chg_continue_ack(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch (event) {
+ case NACC_EV_TIMEOUT_CELL_CHG_CONTINUE:
+ nacc_fsm_state_chg(fi, NACC_ST_TX_CELL_CHG_CONTINUE);
+ break;
+ case NACC_EV_RX_CELL_CHG_CONTINUE_ACK:
nacc_fsm_state_chg(fi, NACC_ST_DONE);
break;
default:
@@ -543,10 +573,20 @@
X(NACC_EV_RX_SI) |
X(NACC_EV_CREATE_RLCMAC_MSG),
.out_state_mask =
- X(NACC_ST_DONE),
+ X(NACC_ST_WAIT_CELL_CHG_CONTINUE_ACK),
.name = "TX_CELL_CHG_CONTINUE",
.action = st_cell_chg_continue,
},
+ [NACC_ST_WAIT_CELL_CHG_CONTINUE_ACK] = {
+ .in_event_mask =
+ X(NACC_EV_RX_CELL_CHG_CONTINUE_ACK) |
+ X(NACC_EV_TIMEOUT_CELL_CHG_CONTINUE),
+ .out_state_mask =
+ X(NACC_ST_TX_CELL_CHG_CONTINUE) |
+ X(NACC_ST_DONE),
+ .name = "WAIT_CELL_CHG_CONTINUE_ACK",
+ .action = st_wait_cell_chg_continue_ack,
+ },
[NACC_ST_DONE] = {
.in_event_mask = 0,
.out_state_mask = 0,