pespin submitted this change.

View Change


Approvals: Jenkins Builder: Verified pespin: Looks good to me, approved
rlcmac: Use finished UL TBF to request a new one after Final UL ACK/NACK

Change-Id: I4eb873250f5ee7eafb5b6126382ce088091d0447
---
M include/osmocom/gprs/rlcmac/tbf_ul.h
M include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h
M include/osmocom/gprs/rlcmac/tbf_ul_fsm.h
M src/rlcmac/sched.c
M src/rlcmac/tbf_ul.c
M src/rlcmac/tbf_ul_ass_fsm.c
M src/rlcmac/tbf_ul_fsm.c
M tests/rlcmac/rlcmac_prim_test.c
M tests/rlcmac/rlcmac_prim_test.err
M tests/rlcmac/rlcmac_prim_test.ok
10 files changed, 289 insertions(+), 15 deletions(-)

diff --git a/include/osmocom/gprs/rlcmac/tbf_ul.h b/include/osmocom/gprs/rlcmac/tbf_ul.h
index 32d7036..3382778 100644
--- a/include/osmocom/gprs/rlcmac/tbf_ul.h
+++ b/include/osmocom/gprs/rlcmac/tbf_ul.h
@@ -47,6 +47,8 @@

bool gprs_rlcmac_ul_tbf_in_contention_resolution(const struct gprs_rlcmac_ul_tbf *ul_tbf);
unsigned int gprs_rlcmac_ul_tbf_n3104_max(const struct gprs_rlcmac_ul_tbf *ul_tbf);
+bool gprs_rlcmac_ul_tbf_have_data(const struct gprs_rlcmac_ul_tbf *ul_tbf);
+bool gprs_rlcmac_ul_tbf_can_request_new_ul_tbf(const struct gprs_rlcmac_ul_tbf *ul_tbf);
bool gprs_rlcmac_ul_tbf_data_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi);
bool gprs_rlcmac_ul_tbf_dummy_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi);

diff --git a/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h b/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h
index d1159d5..4a1658d 100644
--- a/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h
+++ b/include/osmocom/gprs/rlcmac/tbf_ul_ass_fsm.h
@@ -46,6 +46,7 @@

enum tbf_ul_ass_fsm_event {
GPRS_RLCMAC_TBF_UL_ASS_EV_START, /* Start Uplink assignment (data: enum gprs_rlcmac_tbf_ul_ass_type) */
+ GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE, /* Start Uplink assignment directly into 2phase from an older UL TBF */
GPRS_RLCMAC_TBF_UL_ASS_EV_RX_CCCH_IMM_ASS, /* (data: struct tbf_ul_ass_ev_rx_ccch_imm_ass_ctx *) */
GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG, /* Generate RLC/MAC block (data: struct tbf_ul_ass_ev_create_rlcmac_msg_ctx) */
GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS, /* (data: decoded PktUlAss) */
@@ -71,6 +72,7 @@
void gprs_rlcmac_tbf_ul_ass_fsm_destructor(struct gprs_rlcmac_ul_tbf *ul_tbf);

int gprs_rlcmac_tbf_ul_ass_start(struct gprs_rlcmac_ul_tbf *ul_tbf, enum gprs_rlcmac_tbf_ul_ass_type type);
+int gprs_rlcmac_tbf_ul_ass_start_from_releasing_ul_tbf(struct gprs_rlcmac_ul_tbf *ul_tbf, struct gprs_rlcmac_ul_tbf *old_ul_tbf);
bool gprs_rlcmac_tbf_ul_ass_pending(struct gprs_rlcmac_ul_tbf *ul_tbf);
bool gprs_rlcmac_tbf_ul_ass_match_rach_req(struct gprs_rlcmac_ul_tbf *ul_tbf, uint8_t ra);
bool gprs_rlcmac_tbf_ul_ass_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi);
diff --git a/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h b/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h
index acee6f1..cfdb677 100644
--- a/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h
+++ b/include/osmocom/gprs/rlcmac/tbf_ul_fsm.h
@@ -11,7 +11,8 @@
GPRS_RLCMAC_TBF_UL_ST_NEW = 0, /* new created TBF */
GPRS_RLCMAC_TBF_UL_ST_WAIT_ASSIGN, /* wait for Immediate Assignment */
GPRS_RLCMAC_TBF_UL_ST_FLOW, /* RLC/MAC flow, resource needed */
- GPRS_RLCMAC_TBF_UL_ST_FINISHED, /* flow finished, wait for release */
+ GPRS_RLCMAC_TBF_UL_ST_FINISHED, /* All data transmitted (CV=0), only retransmits and waiting for ACKs */
+ GPRS_RLCMAC_TBF_UL_ST_RELEASING, /* Network sent UL ACK w/ FinalAck=1 and polled for response */
};

struct gprs_rlcmac_tbf_ul_fsm_ctx {
@@ -24,6 +25,10 @@
unsigned int pkt_acc_proc_attempts;
/* 9.3.3.3.2: The block with CV=0 shall not be retransmitted more than four times. */
unsigned int last_data_block_retrans_attempts;
+ /* Whether the Received Packet UL ACK/NACK w/ FinalAck=1 had 'TBF Est' field to '1'.
+ * Used during ST_RELEASING to find out if a new UL TBF can be recreated
+ * when ansering the final UL ACK. */
+ bool rx_final_pkt_ul_ack_nack_has_tbf_est;
};

enum tbf_ul_fsm_event {
@@ -33,7 +38,7 @@
GPRS_RLCMAC_TBF_UL_EV_N3104_MAX,
GPRS_RLCMAC_TBF_UL_EV_CONTENTION_RESOLUTION_SUCCESS,
GPRS_RLCMAC_TBF_UL_EV_LAST_UL_DATA_SENT,
- GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD,
+ GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD, /* data: bool TBF_EST */
};

int gprs_rlcmac_tbf_ul_fsm_init(void);
diff --git a/src/rlcmac/sched.c b/src/rlcmac/sched.c
index 5a3fae8..b5c02cc 100644
--- a/src/rlcmac/sched.c
+++ b/src/rlcmac/sched.c
@@ -34,6 +34,7 @@
struct tbf_sched_ctrl_candidates {
struct gprs_rlcmac_dl_tbf *poll_dl_ack_final_ack; /* 8.1.2.2 1) */
struct gprs_rlcmac_dl_tbf *poll_dl_ack; /* 8.1.2.2 7) */
+ struct gprs_rlcmac_ul_tbf *poll_ul_ack_new_ul_tbf; /* 9.3.2.4.2 (answer with PKT RES REQ) */
struct gprs_rlcmac_ul_tbf *poll_ul_ack; /* 11.2.2 (answer with PKT CTRL ACK) */
struct gprs_rlcmac_ul_tbf *ul_ass;
};
@@ -89,8 +90,26 @@
/* TODO */
break;
case GPRS_RLCMAC_PDCH_ULC_POLL_UL_ACK:
+ /* TS 44.060: 9.3.2.4.2 If the PACKET UPLINK ACK/NACK message
+ * has the Final Ack Indicator bit set to '1' and the following
+ * conditions are fulfilled: TBF Est field is set to '1'; the
+ * mobile station has new data to transmit; the mobile station
+ * has no other ongoing downlink TBFs, the mobile station shall
+ * release the uplink TBF and may request the establishment of a
+ * new TBF using one of the following procedures.
+ * If Control Ack Type parameter in System Information indicates
+ * acknowledgement is RLC/MAC control block, the mobile station
+ * shall transmit the PACKET RESOURCE REQUEST message and start
+ * timer T3168 for the TBF request. The mobile station shall use
+ * the same procedures as are used for TBF establishment using two
+ * phase access described in sub-clause 7.1.3 starting from the
+ * point where the mobile station transmits the PACKET RESOURCE
+ * REQUEST message. */
ul_tbf = tbf_as_ul_tbf(node->tbf);
- tbfs->poll_ul_ack = ul_tbf;
+ if (gprs_rlcmac_ul_tbf_can_request_new_ul_tbf(ul_tbf))
+ tbfs->poll_ul_ack_new_ul_tbf = ul_tbf;
+ else
+ tbfs->poll_ul_ack = ul_tbf;
break;
case GPRS_RLCMAC_PDCH_ULC_POLL_DL_ACK:
dl_tbf = tbf_as_dl_tbf(node->tbf);
@@ -148,6 +167,9 @@
struct tbf_sched_ctrl_candidates *tbfs)
{
struct msgb *msg = NULL;
+ struct gprs_rlcmac_entity *gre;
+ int rc;
+
/* 8.1.2.2 1) (EGPRS) PACKET DOWNLINK ACK/NACK w/ FinalAckInd=1 */
if (tbfs->poll_dl_ack_final_ack) {
LOGRLCMAC(LOGL_DEBUG, "(ts=%u,fn=%u,usf=%u) Tx DL ACK/NACK FinalAck=1\n",
@@ -158,12 +180,36 @@
}

/* 8.1.2.2 5) Any other RLC/MAC control message, other than a (EGPRS) PACKET DOWNLINK ACK/NACK */
+ if (tbfs->poll_ul_ack_new_ul_tbf) {
+ LOGRLCMAC(LOGL_DEBUG, "(ts=%u,fn=%u,usf=%u) Tx Pkt Resource Request (UL ACK/NACK poll)\n",
+ bi->ts, bi->fn, bi->usf);
+ gre = tbfs->poll_ul_ack_new_ul_tbf->tbf.gre;
+ OSMO_ASSERT(gre->ul_tbf == tbfs->poll_ul_ack_new_ul_tbf);
+ gre->ul_tbf = gprs_rlcmac_ul_tbf_alloc(gre);
+ if (!gre->ul_tbf) {
+ gprs_rlcmac_ul_tbf_free(tbfs->poll_ul_ack_new_ul_tbf);
+ return NULL;
+ }
+ /* Prepare new UL TBF from old UL TBF: */
+ rc = gprs_rlcmac_tbf_ul_ass_start_from_releasing_ul_tbf(gre->ul_tbf, tbfs->poll_ul_ack_new_ul_tbf);
+ gprs_rlcmac_ul_tbf_free(tbfs->poll_ul_ack_new_ul_tbf); /* always free */
+ if (rc < 0) {
+ gprs_rlcmac_ul_tbf_free(gre->ul_tbf);
+ return NULL;
+ }
+ /* New UL TBF is ready to send the Pkt Res Req: */
+ OSMO_ASSERT(gprs_rlcmac_tbf_ul_ass_rts(gre->ul_tbf, bi));
+ msg = gprs_rlcmac_tbf_ul_ass_create_rlcmac_msg(gre->ul_tbf, bi);
+ if (msg)
+ return msg;
+ }
if (tbfs->poll_ul_ack) {
LOGRLCMAC(LOGL_DEBUG, "(ts=%u,fn=%u,usf=%u) Tx Pkt Control Ack (UL ACK/NACK poll)\n",
bi->ts, bi->fn, bi->usf);
msg = gprs_rlcmac_ul_tbf_create_pkt_ctrl_ack(tbfs->poll_ul_ack);
- if (msg)
- return msg;
+ /* Last UL message, freeing */
+ gprs_rlcmac_ul_tbf_free(tbfs->poll_ul_ack);
+ return msg;
}
if (tbfs->ul_ass) {
msg = gprs_rlcmac_tbf_ul_ass_create_rlcmac_msg(tbfs->ul_ass, bi);
diff --git a/src/rlcmac/tbf_ul.c b/src/rlcmac/tbf_ul.c
index d3343d0..0b62610 100644
--- a/src/rlcmac/tbf_ul.c
+++ b/src/rlcmac/tbf_ul.c
@@ -123,6 +123,36 @@
return 3 * (bs_cv_max + 3) * ul_tbf->cur_alloc.num_ts;
}

+/* Whether the existing UL TBF can directly request a new UL TBF instead of goig to packet idle mode. */
+bool gprs_rlcmac_ul_tbf_can_request_new_ul_tbf(const struct gprs_rlcmac_ul_tbf *ul_tbf)
+{
+ /* 9.3.2.4.2: "If the PACKET UPLINK ACK/NACK message has the Final Ack Indicator
+ * bit set to '1' and the following conditions are fulfilled: TBF Est field is set
+ * to '1'; the mobile station has new data to transmit; the mobile station has no
+ * other ongoing downlink TBFs, the mobile station shall release the uplink TBF and
+ * may request the establishment of a new TBF"
+ */
+
+ /* "PACKET UPLINK ACK/NACK message has the Final Ack Indicator" means GPRS_RLCMAC_TBF_UL_ST_RELEASING: */
+ if (gprs_rlcmac_tbf_ul_state(ul_tbf) != GPRS_RLCMAC_TBF_UL_ST_RELEASING)
+ return false;
+
+ /* "TBF Est field is set to '1'"" */
+ if (!ul_tbf->state_fsm.rx_final_pkt_ul_ack_nack_has_tbf_est)
+ return false;
+
+ /* the mobile station has new data to transmit */
+ if (!gprs_rlcmac_ul_tbf_have_data(ul_tbf))
+ return false;
+
+ /* "the mobile station has no other ongoing downlink TBFs */
+ if (ul_tbf->tbf.gre->dl_tbf)
+ return false;
+
+ return true;
+
+}
+
/* Used by the scheduler to find out whether an Uplink Dummy Control Block can be transmitted. If
* true, it will potentially call gprs_rlcmac_ul_tbf_dummy_create() to generate a new dummy message to transmit. */
bool gprs_rlcmac_ul_tbf_dummy_rts(const struct gprs_rlcmac_ul_tbf *ul_tbf, const struct gprs_rlcmac_rts_block_ind *bi)
@@ -182,20 +212,22 @@
return 0;
}

-int gprs_rlcmac_ul_tbf_handle_final_ack(struct gprs_rlcmac_ul_tbf *ul_tbf)
+int gprs_rlcmac_ul_tbf_handle_final_ack(struct gprs_rlcmac_ul_tbf *ul_tbf, const RlcMacDownlink_t *dl_block)
{
int rc = 0;
+ bool tbf_est = false;
+ const PU_AckNack_GPRS_t *ack_gprs = &dl_block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct;

- osmo_fsm_inst_dispatch(ul_tbf->state_fsm.fi, GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD, NULL);
+ if (ack_gprs->Exist_AdditionsR99)
+ tbf_est = ack_gprs->AdditionsR99.TBF_EST;
+
+ osmo_fsm_inst_dispatch(ul_tbf->state_fsm.fi, GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD, &tbf_est);

/* range V(A)..V(S)-1 */
//received = gprs_rlcmac_rlc_ul_window_count_unacked(ul_tbf->ulw);
/* report all outstanding packets as received */
//gprs_rlcmac_received_lost(this, received, 0);
gprs_rlcmac_rlc_ul_window_reset(ul_tbf->ulw);
-
- /* TODO: check for RRBP and attempt to create a new UL TBF if
- * gprs_rlcmac_ul_tbf_have_data(ul_tbf) */
return rc;
}

@@ -232,7 +264,7 @@

if (ack_desc->FINAL_ACK_INDICATION) {
LOGPTBFUL(ul_tbf, LOGL_DEBUG, "Final ACK received.\n");
- rc = gprs_rlcmac_ul_tbf_handle_final_ack(ul_tbf);
+ rc = gprs_rlcmac_ul_tbf_handle_final_ack(ul_tbf, dl_block);
} else if (gprs_rlcmac_tbf_ul_state(ul_tbf) &&
gprs_rlcmac_rlc_ul_window_window_empty(ul_tbf->ulw)) {
LOGPTBFUL(ul_tbf, LOGL_NOTICE,
diff --git a/src/rlcmac/tbf_ul_ass_fsm.c b/src/rlcmac/tbf_ul_ass_fsm.c
index a382ab2..6169080 100644
--- a/src/rlcmac/tbf_ul_ass_fsm.c
+++ b/src/rlcmac/tbf_ul_ass_fsm.c
@@ -37,6 +37,7 @@

static const struct value_string tbf_ul_ass_fsm_event_names[] = {
{ GPRS_RLCMAC_TBF_UL_ASS_EV_START, "START" },
+ { GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE, "START_DIRECT_2PHASE" },
{ GPRS_RLCMAC_TBF_UL_ASS_EV_RX_CCCH_IMM_ASS, "RX_CCCH_IMM_ASS" },
{ GPRS_RLCMAC_TBF_UL_ASS_EV_CREATE_RLCMAC_MSG, "CREATE_RLCMAC_MSG" },
{ GPRS_RLCMAC_TBF_UL_ASS_EV_RX_PKT_UL_ASS, "RX_PKT_UL_ASS" },
@@ -185,6 +186,11 @@
submit_rach_req(ctx);
tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS);
break;
+ case GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE:
+ osmo_fsm_inst_dispatch(ctx->ul_tbf->state_fsm.fi, GPRS_RLCMAC_TBF_UL_EV_UL_ASS_START, NULL);
+ ctx->ass_type = GPRS_RLCMAC_TBF_UL_ASS_TYPE_2PHASE;
+ tbf_ul_ass_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -279,9 +285,11 @@
static struct osmo_fsm_state tbf_ul_ass_fsm_states[] = {
[GPRS_RLCMAC_TBF_UL_ASS_ST_IDLE] = {
.in_event_mask =
- X(GPRS_RLCMAC_TBF_UL_ASS_EV_START),
+ X(GPRS_RLCMAC_TBF_UL_ASS_EV_START) |
+ X(GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE),
.out_state_mask =
- X(GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS),
+ X(GPRS_RLCMAC_TBF_UL_ASS_ST_WAIT_CCCH_IMM_ASS) |
+ X(GPRS_RLCMAC_TBF_UL_ASS_ST_SCHED_PKT_RES_REQ),
.name = "IDLE",
.onenter = st_idle_on_enter,
.action = st_idle,
@@ -403,6 +411,19 @@
return rc;
}

+/* A releasing TBF being polled is used to fill in 1phase access internally and
+* switch the FSM to trigger the 2hpase directly (tx Pkt Res Req) */
+int gprs_rlcmac_tbf_ul_ass_start_from_releasing_ul_tbf(struct gprs_rlcmac_ul_tbf *ul_tbf, struct gprs_rlcmac_ul_tbf *old_ul_tbf)
+{
+ int rc;
+ memcpy(&ul_tbf->ul_ass_fsm.phase1_alloc, &old_ul_tbf->cur_alloc,
+ sizeof(ul_tbf->ul_ass_fsm.phase1_alloc));
+ rc = osmo_fsm_inst_dispatch(ul_tbf->ul_ass_fsm.fi,
+ GPRS_RLCMAC_TBF_UL_ASS_EV_START_DIRECT_2PHASE,
+ NULL);
+ return rc;
+}
+
bool gprs_rlcmac_tbf_ul_ass_pending(struct gprs_rlcmac_ul_tbf *ul_tbf)
{
return ul_tbf->ul_ass_fsm.fi->state != GPRS_RLCMAC_TBF_UL_ASS_ST_IDLE;
diff --git a/src/rlcmac/tbf_ul_fsm.c b/src/rlcmac/tbf_ul_fsm.c
index 3ecb41d..cb7df60 100644
--- a/src/rlcmac/tbf_ul_fsm.c
+++ b/src/rlcmac/tbf_ul_fsm.c
@@ -196,12 +196,23 @@
}
break;
case GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD:
+ ctx->rx_final_pkt_ul_ack_nack_has_tbf_est = *((bool *)data);
+ tbf_ul_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ST_RELEASING);
break;
default:
OSMO_ASSERT(0);
}
}

+static void st_releasing(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ //struct gprs_rlcmac_tbf_ul_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_ul_fsm_ctx *)fi->priv;
+ switch (event) {
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
static struct osmo_fsm_state tbf_ul_fsm_states[] = {
[GPRS_RLCMAC_TBF_UL_ST_NEW] = {
.in_event_mask =
@@ -240,10 +251,17 @@
X(GPRS_RLCMAC_TBF_UL_EV_LAST_UL_DATA_SENT) |
X(GPRS_RLCMAC_TBF_UL_EV_FINAL_ACK_RECVD),
.out_state_mask =
- X(GPRS_RLCMAC_TBF_UL_ST_NEW),
+ X(GPRS_RLCMAC_TBF_UL_ST_NEW) |
+ X(GPRS_RLCMAC_TBF_UL_ST_RELEASING),
.name = "FINISHED",
.action = st_finished,
},
+ [GPRS_RLCMAC_TBF_UL_ST_RELEASING] = {
+ .in_event_mask = 0,
+ .out_state_mask = 0,
+ .name = "RELEASING",
+ .action = st_releasing,
+ },
};

static int tbf_ul_fsm_timer_cb(struct osmo_fsm_inst *fi)
diff --git a/tests/rlcmac/rlcmac_prim_test.c b/tests/rlcmac/rlcmac_prim_test.c
index c9bd2ff..96cc6d9 100644
--- a/tests/rlcmac/rlcmac_prim_test.c
+++ b/tests/rlcmac/rlcmac_prim_test.c
@@ -520,6 +520,74 @@
cleanup_test();
}

+/* Test UL TBF requesting assignment of a new UL TBF through PACCH when
+ * answering UL ACK/NACK w/ FinalACK=1 */
+static void test_ul_tbf_request_another_ul_tbf(void)
+{
+ struct osmo_gprs_rlcmac_prim *rlcmac_prim;
+ int rc;
+
+ printf("=== %s start ===\n", __func__);
+ prepare_test();
+ RlcMacDownlink_t dl_block;
+ PU_AckNack_GPRS_t *ack_gprs = &dl_block.u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct;
+ Ack_Nack_Description_t *ack_desc = &ack_gprs->Ack_Nack_Description;
+ uint32_t tlli = 0x2342;
+ uint8_t ul_tfi = 0;
+ uint8_t ts_nr = 7;
+ uint8_t usf = 0;
+ uint32_t rts_fn = 4;
+
+ /* Send only 14 data to feed it in 1 UL block and speed up test length: */
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req,
+ 14);
+ rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
+ rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
+
+ OSMO_ASSERT(sizeof(ccch_imm_ass_pkt_ul_tbf_normal) == GSM_MACBLOCK_LEN);
+ ccch_imm_ass_pkt_ul_tbf_normal[7] = last_rach_req_ra; /* Update RA to match */
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_ccch_data_ind(0, ccch_imm_ass_pkt_ul_tbf_normal);
+ rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
+
+ /* Trigger transmission of LLC data (GMM Attach) */
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
+ rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
+ OSMO_ASSERT(rc == 0);
+
+ /* PCU acks it: */
+ ul_ack_nack_init(&dl_block, ul_tfi, GPRS_RLCMAC_CS_2);
+ ack_desc->STARTING_SEQUENCE_NUMBER = 1;
+ ack_desc->FINAL_ACK_INDICATION = 1;
+ ul_ack_nack_mark(ack_desc, 0, true);
+ ul_ack_nack_mark(ack_desc, 1, true);
+ /* TBF Est is set: */
+ ack_gprs->Exist_AdditionsR99 = 1;
+ ack_gprs->AdditionsR99.TBF_EST = 1;
+ /* Final ACK has Poll set: */
+ dl_block.SP = 1;
+ dl_block.RRBP = GPRS_RLCMAC_RRBP_N_plus_13;
+ rlcmac_prim = create_dl_ctrl_block(&dl_block, ts_nr, rts_fn);
+ rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
+ OSMO_ASSERT(rc == 0);
+
+ /* New data from upper layers arrive which needs to be transmitted. This
+ * will make UL_TBF request a new UL_TBF when triggered to answer the final
+ * UL ACK/NACK, because there's no active DL TBF: */
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_grr_unitdata_req(tlli, pdu_llc_gmm_att_req,
+ 14);
+ rlcmac_prim->grr.unitdata_req.sapi = OSMO_GPRS_RLCMAC_LLC_SAPI_GMM;
+ rc = osmo_gprs_rlcmac_prim_upper_down(rlcmac_prim);
+
+ /* Trigger transmission of PKT RES REQ: */
+ rts_fn = rrbp2fn(rts_fn, dl_block.RRBP);
+ rlcmac_prim = osmo_gprs_rlcmac_prim_alloc_l1ctl_pdch_rts_ind(ts_nr, rts_fn, usf);
+ rc = osmo_gprs_rlcmac_prim_lower_up(rlcmac_prim);
+ OSMO_ASSERT(rc == 0);
+
+ printf("=== %s end ===\n", __func__);
+ cleanup_test();
+}
+
static void test_ul_tbf_t3164_timeout(void)
{
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
@@ -773,6 +841,7 @@
test_ul_tbf_t3166_timeout();
test_ul_tbf_n3104_timeout();
test_ul_tbf_last_data_cv0_retrans_max();
+ test_ul_tbf_request_another_ul_tbf();
test_dl_tbf_ccch_assign();

talloc_free(tall_ctx);
diff --git a/tests/rlcmac/rlcmac_prim_test.err b/tests/rlcmac/rlcmac_prim_test.err
index 1337c44..e84461f 100644
--- a/tests/rlcmac/rlcmac_prim_test.err
+++ b/tests/rlcmac/rlcmac_prim_test.err
@@ -53,12 +53,13 @@
DLGLOBAL INFO UL_TBF{FINISHED}: Contention resolution succeeded, stop T3166
DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Final ACK received.
DLGLOBAL INFO UL_TBF{FINISHED}: Received Event FINAL_ACK_RECVD
+DLGLOBAL INFO UL_TBF{FINISHED}: state_chg to RELEASING
DLGLOBAL DEBUG Register POLL (TS=7 FN=21, reason=UL_ACK)
DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_RTS.indication
DLGLOBAL DEBUG (ts=7,fn=21,usf=0) Tx Pkt Control Ack (UL ACK/NACK poll)
DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Tx Packet Control Ack
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
-DLGLOBAL INFO UL_TBF{FINISHED}: Deallocated
+DLGLOBAL INFO UL_TBF{RELEASING}: Deallocated
DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request
DLGLOBAL INFO TLLI=0x00002342 not found, creating entity on the fly
DLGLOBAL INFO UL_TBF{NEW}: Allocated
@@ -471,6 +472,68 @@
DLGLOBAL NOTICE UL_TBF{FINISHED}: TBF establishment failure (Data block with CV=0 retransmit attempts=4)
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
DLGLOBAL INFO UL_TBF{FINISHED}: Deallocated
+DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request
+DLGLOBAL INFO TLLI=0x00002342 not found, creating entity on the fly
+DLGLOBAL INFO UL_TBF{NEW}: Allocated
+DLGLOBAL INFO UL_TBF_ASS{IDLE}: Allocated
+DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START
+DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START
+DLGLOBAL INFO UL_TBF{NEW}: state_chg to ASSIGN
+DLGLOBAL INFO UL_TBF_ASS{IDLE}: Send RACH.req ra=0x7b
+DLGLOBAL INFO UL_TBF_ASS{IDLE}: state_chg to WAIT_CCCH_IMM_ASS
+DLGLOBAL INFO Rx from lower layers: L1CTL-CCCH_DATA.indication
+DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: Received Event RX_CCCH_IMM_ASS
+DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss initial CS=CS-2
+DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
+DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
+DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
+DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
+DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_RTS.indication
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Sending new block at BSN 0, CS=CS-2
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Dequeue next LLC (len=14)
+DLGLOBAL DEBUG -- Chunk with length 14 is less than remaining space (26): add length header to delimit LLC frame
+DLGLOBAL DEBUG -- Final block, so we done.
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Complete UL frame, len=0
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) data block (BSN 0, CS-2): 39 00 00 23 42 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) need_padding 0 spb_status 0 spb 0 (BSN1 0 BSN2 -1)
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Copying 1 RLC blocks, 1 BSNs
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Copying data unit 0 (BSN 0)
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) msg block (BSN 0, CS-2): 00 00 00 39 00 00 23 42 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00
+DLGLOBAL INFO UL_TBF{FLOW}: Received Event FIRST_UL_DATA_SENT
+DLGLOBAL INFO UL_TBF{FLOW}: First UL block sent, stop T3164
+DLGLOBAL INFO UL_TBF{FLOW}: First UL block sent (1 phase access), start T3166
+DLGLOBAL INFO UL_TBF{FLOW}: Received Event LAST_UL_DATA_SENT
+DLGLOBAL INFO UL_TBF{FLOW}: state_chg to FINISHED
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) N3104 inc (1)
+DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_DATA.indication
+DLGLOBAL INFO TS=7 FN=4 Rx Pkt UL ACK/NACK
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Got GPRS UL ACK bitmap: SSN: 1, BSN 0 to 1 - 1 (1 blocks), "R"
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) ack: (BSN=0)"R"(BSN=0) R=ACK I=NACK
+DLGLOBAL DEBUG - got ack for BSN=0
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) V(B): (V(A)=1)""(V(S)-1=0) A=Acked N=Nacked U=Unacked X=Resend-Unacked I=Invalid
+DLGLOBAL INFO UL_TBF{FINISHED}: Received Event CONTENTION_RESOLUTION_SUCCESS
+DLGLOBAL INFO UL_TBF{FINISHED}: Contention resolution succeeded, stop T3166
+DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Final ACK received.
+DLGLOBAL INFO UL_TBF{FINISHED}: Received Event FINAL_ACK_RECVD
+DLGLOBAL INFO UL_TBF{FINISHED}: state_chg to RELEASING
+DLGLOBAL DEBUG Register POLL (TS=7 FN=17, reason=UL_ACK)
+DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request
+DLGLOBAL INFO Rx from lower layers: L1CTL-PDCH_RTS.indication
+DLGLOBAL DEBUG (ts=7,fn=17,usf=0) Tx Pkt Resource Request (UL ACK/NACK poll)
+DLGLOBAL INFO UL_TBF{NEW}: Allocated
+DLGLOBAL INFO UL_TBF_ASS{IDLE}: Allocated
+DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START_DIRECT_2PHASE
+DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START
+DLGLOBAL INFO UL_TBF{NEW}: state_chg to ASSIGN
+DLGLOBAL INFO UL_TBF_ASS{IDLE}: state_chg to SCHED_PKT_RES_REQ
+DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
+DLGLOBAL INFO UL_TBF{RELEASING}: Deallocated
+DLGLOBAL INFO UL_TBF_ASS{SCHED_PKT_RES_REQ}: Received Event CREATE_RLCMAC_MSG
+DLGLOBAL INFO UL_TBF_ASS{SCHED_PKT_RES_REQ}: state_chg to WAIT_PKT_UL_ASS
+DLGLOBAL INFO UL_TBF_ASS{WAIT_PKT_UL_ASS}: Deallocated
+DLGLOBAL INFO UL_TBF{ASSIGN}: Deallocated
DLGLOBAL INFO Rx from upper layers: GMMRR-ASSIGN.request
DLGLOBAL INFO GMMRR-ASSIGN.req: creating new entity TLLI=0x00000001
DLGLOBAL INFO Rx from lower layers: L1CTL-CCCH_DATA.indication
diff --git a/tests/rlcmac/rlcmac_prim_test.ok b/tests/rlcmac/rlcmac_prim_test.ok
index bfe2598..fdd570f 100644
--- a/tests/rlcmac/rlcmac_prim_test.ok
+++ b/tests/rlcmac/rlcmac_prim_test.ok
@@ -95,6 +95,13 @@
RTS 3: FN=26
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=26 ts=7 data_len=34 data=[00 00 02 1d 11 e5 10 00 e2 18 f2 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ]
=== test_ul_tbf_last_data_cv0_retrans_max end ===
+=== test_ul_tbf_request_another_ul_tbf start ===
+sys={0.000000}, mono={0.000000}: clock_override_set
+test_rlcmac_prim_down_cb(): Rx L1CTL-RACH.request ra=0x7b
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x80
+test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=4 ts=7 data_len=34 data=[00 00 00 39 00 00 23 42 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ]
+test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=17 ts=7 data_len=23 data=[40 16 40 00 08 d0 a0 bc 00 00 00 00 00 00 70 00 38 00 00 2b 2b 2b 2b ]
+=== test_ul_tbf_request_another_ul_tbf end ===
=== test_dl_tbf_ccch_assign start ===
sys={0.000000}, mono={0.000000}: clock_override_set
test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_DL_TBF.request dl_tbf_nr=0 dl_slotmask=0x80 dl_tfi=0

To view, visit change 31446. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I4eb873250f5ee7eafb5b6126382ce088091d0447
Gerrit-Change-Number: 31446
Gerrit-PatchSet: 2
Gerrit-Owner: pespin <pespin@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: pespin <pespin@sysmocom.de>
Gerrit-MessageType: merged