pdch_ulc: Store TBF poll reason

This allows easily checking the initial reason to trigger the poll when
either it is received or times out.

Later on this reason can be transformed into an FSM event and sent to
the related FSM.

Related: OS#5020
Change-Id: Ie8fefd1f47ad674ce597a8065b15284088956bde
changes/25/23525/2
Pau Espin 2 years ago
parent b5ae0811d1
commit 86580e1966
  1. 2
      src/nacc_fsm.c
  2. 4
      src/pdch.cpp
  3. 5
      src/pdch_ul_controller.c
  4. 11
      src/pdch_ul_controller.h
  5. 30
      src/tbf.cpp
  6. 17
      src/tbf.h
  7. 2
      src/tbf_dl.cpp
  8. 6
      src/tbf_ul.cpp
  9. 2
      src/tbf_ul.h
  10. 12
      tests/ulc/PdchUlcTest.cpp

@ -206,7 +206,7 @@ static struct msgb *create_packet_cell_chg_continue(const struct nacc_fsm_ctx *c
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);
tbf_set_polling(tbf, *new_poll_fn, data->ts, PDCH_ULC_POLL_CELL_CHG_CONTINUE);
return msg;
free_ret:

@ -306,6 +306,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
uint32_t tlli = packet->TLLI;
GprsMs *ms = bts_ms_by_tlli(bts(), tlli, GSM_RESERVED_TMSI);
gprs_rlcmac_ul_tbf *ul_tbf;
enum pdch_ulc_tbf_poll_reason reason;
struct pdch_ulc_node *poll;
poll = pdch_ulc_get_node(ulc, fn);
@ -325,6 +326,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
return;
}
tbf = poll->tbf_poll.poll_tbf;
reason = poll->tbf_poll.reason;
/* Reset N3101 counter: */
tbf->n_reset(N3101);
@ -337,7 +339,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
/* check if this control ack belongs to packet uplink ack */
ul_tbf = as_ul_tbf(tbf);
if (ul_tbf && ul_tbf->handle_ctrl_ack()) {
if (ul_tbf && ul_tbf->handle_ctrl_ack(reason)) {
LOGPTBF(tbf, LOGL_DEBUG, "[UPLINK] END\n");
if (ul_tbf->ctrl_ack_to_toggle())
LOGPTBF(tbf, LOGL_NOTICE, "Recovered uplink ack for UL\n");

@ -220,11 +220,12 @@ int pdch_ulc_reserve_tbf_usf(struct pdch_ulc *ulc, uint32_t fn, struct gprs_rlcm
return pdch_ulc_add_node(ulc, item);
}
int pdch_ulc_reserve_tbf_poll(struct pdch_ulc *ulc, uint32_t fn, struct gprs_rlcmac_tbf *tbf)
int pdch_ulc_reserve_tbf_poll(struct pdch_ulc *ulc, uint32_t fn, struct gprs_rlcmac_tbf *tbf, enum pdch_ulc_tbf_poll_reason reason)
{
struct pdch_ulc_node *item = _alloc_node(ulc, fn);
item->type = PDCH_ULC_NODE_TBF_POLL;
item->tbf_poll.poll_tbf = tbf;
item->tbf_poll.reason = reason;
return pdch_ulc_add_node(ulc, item);
}
@ -317,7 +318,7 @@ void pdch_ulc_expire_fn(struct pdch_ulc *ulc, uint32_t fn)
LOGPDCH(ulc->pdch, DRLCMAC, LOGL_NOTICE,
"Timeout for registered POLL (FN=%u): %s\n",
item->fn, tbf_name(item->tbf_poll.poll_tbf));
tbf_poll_timeout(item->tbf_poll.poll_tbf);
tbf_poll_timeout(item->tbf_poll.poll_tbf, item->tbf_poll.reason);
break;
case PDCH_ULC_NODE_SBA:
sba = item->sba.sba;

@ -52,6 +52,14 @@ enum PdchUlcNode {
};
extern const struct value_string pdch_ul_node_names[];
enum pdch_ulc_tbf_poll_reason {
PDCH_ULC_POLL_UL_ASS, /* Expect CTRL ACK for UL ASS we transmit */
PDCH_ULC_POLL_DL_ASS, /* Expect CTRL ACK for DL ASS we transmit */
PDCH_ULC_POLL_UL_ACK, /* Expect CTRL ACK for UL ACK/NACK we transmit */
PDCH_ULC_POLL_DL_ACK, /* Expect DL ACK/NACK requested by RRBP */
PDCH_ULC_POLL_CELL_CHG_CONTINUE, /* Expect CTRL ACK for Pkt cell Change Continue we transmit */
};
struct pdch_ulc_node {
struct rb_node node; /*! entry in pdch_ulc->tree_root */
uint32_t fn;
@ -62,6 +70,7 @@ struct pdch_ulc_node {
} tbf_usf;
struct {
struct gprs_rlcmac_tbf *poll_tbf;
enum pdch_ulc_tbf_poll_reason reason;
} tbf_poll;
struct {
struct gprs_rlcmac_sba *sba;
@ -73,7 +82,7 @@ struct pdch_ulc_node {
struct pdch_ulc *pdch_ulc_alloc(struct gprs_rlcmac_pdch *pdch, void *ctx);
int pdch_ulc_reserve_tbf_usf(struct pdch_ulc *ulc, uint32_t fn, struct gprs_rlcmac_ul_tbf *ul_tbf);
int pdch_ulc_reserve_tbf_poll(struct pdch_ulc *ulc, uint32_t fn, struct gprs_rlcmac_tbf *tbf);
int pdch_ulc_reserve_tbf_poll(struct pdch_ulc *ulc, uint32_t fn, struct gprs_rlcmac_tbf *tbf, enum pdch_ulc_tbf_poll_reason reason);
int pdch_ulc_reserve_sba(struct pdch_ulc *ulc, struct gprs_rlcmac_sba *sba);
bool pdch_ulc_fn_is_free(struct pdch_ulc *ulc, uint32_t fn);

@ -572,7 +572,7 @@ int gprs_rlcmac_tbf::check_polling(uint32_t fn, uint8_t ts,
return 0;
}
void gprs_rlcmac_tbf::set_polling(uint32_t new_poll_fn, uint8_t ts, enum gprs_rlcmac_tbf_poll_type t)
void gprs_rlcmac_tbf::set_polling(uint32_t new_poll_fn, uint8_t ts, enum pdch_ulc_tbf_poll_reason reason)
{
const char *chan = "UNKNOWN";
@ -588,7 +588,7 @@ void gprs_rlcmac_tbf::set_polling(uint32_t new_poll_fn, uint8_t ts, enum gprs_rl
chan, new_poll_fn, ts);
/* schedule polling */
if (pdch_ulc_reserve_tbf_poll(trx->pdch[ts].ulc, new_poll_fn, this) < 0) {
if (pdch_ulc_reserve_tbf_poll(trx->pdch[ts].ulc, new_poll_fn, this, reason) < 0) {
LOGPTBFDL(this, LOGL_ERROR, "Failed scheduling poll on %s (FN=%d, TS=%d)\n",
chan, poll_fn, ts);
return;
@ -597,37 +597,37 @@ void gprs_rlcmac_tbf::set_polling(uint32_t new_poll_fn, uint8_t ts, enum gprs_rl
poll_fn = new_poll_fn;
poll_ts = ts;
switch (t) {
case GPRS_RLCMAC_POLL_UL_ASS:
switch (reason) {
case PDCH_ULC_POLL_UL_ASS:
ul_ass_state = GPRS_RLCMAC_UL_ASS_WAIT_ACK;
LOGPTBFDL(this, LOGL_INFO, "Scheduled UL Assignment polling on %s (FN=%d, TS=%d)\n",
chan, poll_fn, poll_ts);
break;
case GPRS_RLCMAC_POLL_DL_ASS:
case PDCH_ULC_POLL_DL_ASS:
dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK;
LOGPTBFDL(this, LOGL_INFO, "Scheduled DL Assignment polling on %s (FN=%d, TS=%d)\n",
chan, poll_fn, poll_ts);
break;
case GPRS_RLCMAC_POLL_UL_ACK:
case PDCH_ULC_POLL_UL_ACK:
ul_ack_state = GPRS_RLCMAC_UL_ACK_WAIT_ACK;
LOGPTBFUL(this, LOGL_DEBUG, "Scheduled UL Acknowledgement polling on %s (FN=%d, TS=%d)\n",
chan, poll_fn, poll_ts);
break;
case GPRS_RLCMAC_POLL_DL_ACK:
case PDCH_ULC_POLL_DL_ACK:
LOGPTBFDL(this, LOGL_DEBUG, "Scheduled DL Acknowledgement polling on %s (FN=%d, TS=%d)\n",
chan, poll_fn, poll_ts);
break;
case GPRS_RLCMAC_POLL_CELL_CHG_CONTINUE:
case PDCH_ULC_POLL_CELL_CHG_CONTINUE:
LOGPTBFDL(this, LOGL_DEBUG, "Scheduled 'Packet Cell Change Continue' polling on %s (FN=%d, TS=%d)\n",
chan, poll_fn, poll_ts);
break;
}
}
void gprs_rlcmac_tbf::poll_timeout()
void gprs_rlcmac_tbf::poll_timeout(enum pdch_ulc_tbf_poll_reason reason)
{
uint16_t pgroup;
gprs_rlcmac_ul_tbf *ul_tbf = as_ul_tbf(this);
@ -637,7 +637,7 @@ void gprs_rlcmac_tbf::poll_timeout()
poll_state = GPRS_RLCMAC_POLL_NONE;
if (ul_tbf && ul_tbf->handle_ctrl_ack()) {
if (ul_tbf && ul_tbf->handle_ctrl_ack(reason)) {
if (!ul_tbf->ctrl_ack_to_toggle()) {
LOGPTBF(this, LOGL_NOTICE,
"Timeout for polling PACKET CONTROL ACK for PACKET UPLINK ACK: %s\n",
@ -945,7 +945,7 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn, uint8_t ts)
bts_do_rate_ctr_inc(bts, CTR_PKT_DL_ASSIGNMENT);
if (poll_ass_dl) {
set_polling(new_poll_fn, ts, GPRS_RLCMAC_POLL_DL_ASS);
set_polling(new_poll_fn, ts, PDCH_ULC_POLL_DL_ASS);
} else {
dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
TBF_SET_STATE(new_dl_tbf, GPRS_RLCMAC_FLOW);
@ -1048,7 +1048,7 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn, uint8_t ts)
LOGP(DTBF, LOGL_DEBUG, "------------------------- TX : Packet Uplink Assignment -------------------------\n");
bts_do_rate_ctr_inc(bts, CTR_PKT_UL_ASSIGNMENT);
set_polling(new_poll_fn, ts, GPRS_RLCMAC_POLL_UL_ASS);
set_polling(new_poll_fn, ts, PDCH_ULC_POLL_UL_ASS);
talloc_free(mac_control_block);
return msg;
@ -1222,12 +1222,12 @@ int tbf_check_polling(const struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts
return tbf->check_polling(fn, ts, poll_fn, rrbp);
}
void tbf_set_polling(struct gprs_rlcmac_tbf *tbf, uint32_t new_poll_fn, uint8_t ts, enum gprs_rlcmac_tbf_poll_type t)
void tbf_set_polling(struct gprs_rlcmac_tbf *tbf, uint32_t new_poll_fn, uint8_t ts, enum pdch_ulc_tbf_poll_reason t)
{
return tbf->set_polling(new_poll_fn, ts, t);
}
void tbf_poll_timeout(struct gprs_rlcmac_tbf *tbf)
void tbf_poll_timeout(struct gprs_rlcmac_tbf *tbf, enum pdch_ulc_tbf_poll_reason reason)
{
tbf->poll_timeout();
tbf->poll_timeout(reason);
}

@ -46,6 +46,7 @@ extern "C" {
#include <osmocom/gsm/gsm48.h>
#include "coding_scheme.h"
#include <pdch_ul_controller.h>
#ifdef __cplusplus
}
#endif
@ -63,14 +64,6 @@ enum gprs_rlcmac_tbf_state {
GPRS_RLCMAC_RELEASING, /* releasing, wait to free TBI/USF */
};
enum gprs_rlcmac_tbf_poll_type {
GPRS_RLCMAC_POLL_UL_ASS,
GPRS_RLCMAC_POLL_DL_ASS,
GPRS_RLCMAC_POLL_UL_ACK,
GPRS_RLCMAC_POLL_DL_ACK,
GPRS_RLCMAC_POLL_CELL_CHG_CONTINUE,
};
enum gprs_rlcmac_tbf_poll_state {
GPRS_RLCMAC_POLL_NONE = 0,
GPRS_RLCMAC_POLL_SCHED, /* a polling was scheduled */
@ -208,8 +201,8 @@ bool tbf_is_tfi_assigned(const struct gprs_rlcmac_tbf *tbf);
uint8_t tbf_tfi(const struct gprs_rlcmac_tbf *tbf);
int tbf_assign_control_ts(struct gprs_rlcmac_tbf *tbf);
int tbf_check_polling(const struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts, uint32_t *poll_fn, unsigned int *rrbp);
void tbf_set_polling(struct gprs_rlcmac_tbf *tbf, uint32_t new_poll_fn, uint8_t ts, enum gprs_rlcmac_tbf_poll_type t);
void tbf_poll_timeout(struct gprs_rlcmac_tbf *tbf);
void tbf_set_polling(struct gprs_rlcmac_tbf *tbf, uint32_t new_poll_fn, uint8_t ts, enum pdch_ulc_tbf_poll_reason t);
void tbf_poll_timeout(struct gprs_rlcmac_tbf *tbf, enum pdch_ulc_tbf_poll_reason reason);
#ifdef __cplusplus
}
#endif
@ -267,8 +260,8 @@ struct gprs_rlcmac_tbf {
int check_polling(uint32_t fn, uint8_t ts,
uint32_t *poll_fn, unsigned int *rrbp) const;
void set_polling(uint32_t poll_fn, uint8_t ts, enum gprs_rlcmac_tbf_poll_type t);
void poll_timeout();
void set_polling(uint32_t poll_fn, uint8_t ts, enum pdch_ulc_tbf_poll_reason reason);
void poll_timeout(enum pdch_ulc_tbf_poll_reason reason);
/** tlli handling */
uint32_t tlli() const;

@ -975,7 +975,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
rc = check_polling(fn, ts, &new_poll_fn, &rrbp);
if (rc >= 0) {
set_polling(new_poll_fn, ts, GPRS_RLCMAC_POLL_DL_ACK);
set_polling(new_poll_fn, ts, PDCH_ULC_POLL_DL_ACK);
m_tx_counter = 0;
/* start timer whenever we send the final block */

@ -275,10 +275,10 @@ bool gprs_rlcmac_ul_tbf::ctrl_ack_to_toggle()
return false; /* GPRS_RLCMAC_FLAG_TO_UL_ACK was unset, now set */
}
bool gprs_rlcmac_ul_tbf::handle_ctrl_ack()
bool gprs_rlcmac_ul_tbf::handle_ctrl_ack(enum pdch_ulc_tbf_poll_reason reason)
{
/* check if this control ack belongs to packet uplink ack */
if (ul_ack_state_is(GPRS_RLCMAC_UL_ACK_WAIT_ACK)) {
if (reason == PDCH_ULC_POLL_UL_ACK && ul_ack_state_is(GPRS_RLCMAC_UL_ACK_WAIT_ACK)) {
TBF_SET_ACK_STATE(this, GPRS_RLCMAC_UL_ACK_NONE);
return true;
}
@ -324,7 +324,7 @@ struct msgb *gprs_rlcmac_ul_tbf::create_ul_ack(uint32_t fn, uint8_t ts)
m_contention_resolution_done = 1;
if (final) {
set_polling(new_poll_fn, ts, GPRS_RLCMAC_POLL_UL_ACK);
set_polling(new_poll_fn, ts, PDCH_ULC_POLL_UL_ACK);
/* waiting for final acknowledge */
m_final_ack_sent = 1;
} else

@ -57,7 +57,7 @@ struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
gprs_rlc_window *window();
struct msgb *create_ul_ack(uint32_t fn, uint8_t ts);
bool ctrl_ack_to_toggle();
bool handle_ctrl_ack();
bool handle_ctrl_ack(enum pdch_ulc_tbf_poll_reason reason);
/* blocks were acked */
int rcv_data_block_acknowledged(
const struct gprs_rlc_data_info *rlc,

@ -88,16 +88,16 @@ static void test_reserve_multiple()
node = pdch_ulc_get_node(pdch->ulc, sba2->fn);
OSMO_ASSERT(node->type == PDCH_ULC_NODE_SBA && node->sba.sba == sba2);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, sba1->fn, tbf1);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, sba1->fn, tbf1, PDCH_ULC_POLL_UL_ASS);
OSMO_ASSERT(rc == -EEXIST);
OSMO_ASSERT(pdch_ulc_get_tbf_poll(pdch->ulc, sba1->fn) == NULL);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, sba2->fn, tbf1);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, sba2->fn, tbf1, PDCH_ULC_POLL_UL_ASS);
OSMO_ASSERT(rc == -EEXIST);
OSMO_ASSERT(pdch_ulc_get_tbf_poll(pdch->ulc, sba2->fn) == NULL);
/* Now Reserve correctly TBF1 */
OSMO_ASSERT(pdch_ulc_fn_is_free(pdch->ulc, tbf1_poll_fn1) == true);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, tbf1_poll_fn1, tbf1);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, tbf1_poll_fn1, tbf1, PDCH_ULC_POLL_UL_ASS);
OSMO_ASSERT(rc == 0);
OSMO_ASSERT(pdch_ulc_get_tbf_poll(pdch->ulc, tbf1_poll_fn1) == tbf1);
OSMO_ASSERT(pdch_ulc_fn_is_free(pdch->ulc, tbf1_poll_fn1) == false);
@ -107,7 +107,7 @@ static void test_reserve_multiple()
/* Now reserve correctly TBF2 */
OSMO_ASSERT(pdch_ulc_fn_is_free(pdch->ulc, tbf2_poll_fn1) == true);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, tbf2_poll_fn1, tbf2);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, tbf2_poll_fn1, tbf2, PDCH_ULC_POLL_UL_ASS);
OSMO_ASSERT(rc == 0);
OSMO_ASSERT(pdch_ulc_get_tbf_poll(pdch->ulc, tbf2_poll_fn1) == tbf2);
OSMO_ASSERT(pdch_ulc_fn_is_free(pdch->ulc, tbf2_poll_fn1) == false);
@ -117,7 +117,7 @@ static void test_reserve_multiple()
/* Now Reserve TBF1 for POLL again on a later FN, which is totally expected: */
OSMO_ASSERT(pdch_ulc_fn_is_free(pdch->ulc, tbf1_poll_fn2) == true);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, tbf1_poll_fn2, tbf1);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, tbf1_poll_fn2, tbf1, PDCH_ULC_POLL_UL_ASS);
OSMO_ASSERT(rc == 0);
OSMO_ASSERT(pdch_ulc_get_tbf_poll(pdch->ulc, tbf1_poll_fn2) == tbf1);
OSMO_ASSERT(pdch_ulc_fn_is_free(pdch->ulc, tbf1_poll_fn2) == false);
@ -182,7 +182,7 @@ static void test_fn_wrap_around()
fn = start_fn;
while (fn < 40 || fn >= start_fn) {
printf("*** RESERVE FN=%" PRIu32 ":\n", fn);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, fn, tbf1);
rc = pdch_ulc_reserve_tbf_poll(pdch->ulc, fn, tbf1, PDCH_ULC_POLL_UL_ASS);
OSMO_ASSERT(rc == 0);
print_ulc_nodes(pdch->ulc);
fn = fn_next_block(fn);

Loading…
Cancel
Save