aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-08-08 08:47:36 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-08-08 08:49:03 +0200
commitf72fcfe2197677ac0252a76d63573929f786cd5f (patch)
tree8c282f6cc6715136b89ab6c6407773764095bb5e
parent1b3864fc472ed82ad35625c8d950d0711a8aa3d6 (diff)
parent7e994e392d9684c6deab2cac3eed162ca96f083d (diff)
Merge remote-tracking branch 'origin/sysmocom/tbf-split'
the TBF handling in osmo-pcu mixes UL and DL TBFs together. They are quite different, however, and should be treated differently. This patch series continues the work of splitting up UL and DL TBFs into their own classes and explicitly using a DL TBF or UL TBF instead of the base class in those parts of the code that deal with only one variant. I didn't test every single commit, but each should compile and the result passes make check as well as our iperf test against a GSM modem. [Text from Daniel's cover mail]
-rw-r--r--src/bts.cpp48
-rw-r--r--src/bts.h2
-rw-r--r--src/encoding.cpp10
-rw-r--r--src/encoding.h4
-rw-r--r--src/gprs_bssgp_pcu.cpp2
-rw-r--r--src/gprs_rlcmac_sched.cpp66
-rw-r--r--src/gprs_rlcmac_ts_alloc.cpp26
-rw-r--r--src/poll_controller.cpp19
-rw-r--r--src/rlc.cpp7
-rw-r--r--src/rlc.h1
-rw-r--r--src/tbf.cpp262
-rw-r--r--src/tbf.h100
-rw-r--r--tests/alloc/AllocTest.cpp10
13 files changed, 287 insertions, 270 deletions
diff --git a/src/bts.cpp b/src/bts.cpp
index 77c3f3ef..73344a38 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -236,14 +236,12 @@ gprs_rlcmac_tbf *BTS::tbf_by_tlli(uint32_t tlli, enum gprs_rlcmac_tbf_direction
struct llist_pods *lpods;
if (dir == GPRS_RLCMAC_UL_TBF) {
llist_pods_for_each_entry(tbf, &m_bts.ul_tbfs, list, lpods) {
- OSMO_ASSERT(tbf->direction == dir);
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
&& tbf->tlli() == tlli && tbf->is_tlli_valid())
return tbf;
}
} else {
llist_pods_for_each_entry(tbf, &m_bts.dl_tbfs, list, lpods) {
- OSMO_ASSERT(tbf->direction == dir);
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)
&& tbf->tlli() == tlli)
return tbf;
@@ -264,7 +262,6 @@ gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
&& tbf->poll_fn == fn && tbf->trx->trx_no == trx
&& tbf->control_ts == ts) {
- OSMO_ASSERT(tbf->direction == GPRS_RLCMAC_DL_TBF);
return static_cast<gprs_rlcmac_dl_tbf *>(tbf);
}
}
@@ -282,7 +279,6 @@ gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts)
&& tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
&& tbf->poll_fn == fn && tbf->trx->trx_no == trx
&& tbf->control_ts == ts) {
- OSMO_ASSERT(tbf->direction == GPRS_RLCMAC_UL_TBF);
return static_cast<gprs_rlcmac_ul_tbf *>(tbf);
}
}
@@ -318,7 +314,6 @@ gprs_rlcmac_tbf *BTS::tbf_by_tfi(uint8_t tfi, uint8_t trx,
return NULL;
if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)) {
- OSMO_ASSERT(tbf->direction == dir);
return tbf;
}
@@ -382,7 +377,7 @@ int BTS::tfi_find_free(enum gprs_rlcmac_tbf_direction dir,
int BTS::rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn)
{
- struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_dl_tbf *dl_tbf;
uint8_t plen;
uint32_t tlli;
@@ -404,8 +399,8 @@ int BTS::rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn)
tlli |= (*data++) << 4;
tlli |= (*data++) >> 4;
- tbf = dl_tbf_by_tlli(tlli);
- if (!tbf) {
+ dl_tbf = dl_tbf_by_tlli(tlli);
+ if (!dl_tbf) {
LOGP(DRLCMAC, LOGL_ERROR, "Got IMM.ASS confirm, but TLLI=%08x "
"does not exit\n", tlli);
return -EINVAL;
@@ -413,8 +408,8 @@ int BTS::rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn)
LOGP(DRLCMAC, LOGL_DEBUG, "Got IMM.ASS confirm for TLLI=%08x\n", tlli);
- if (tbf->dir.dl.wait_confirm)
- tbf_timer_start(tbf, 0, Tassign_agch);
+ if (dl_tbf->m_wait_confirm)
+ tbf_timer_start(dl_tbf, 0, Tassign_agch);
return 0;
}
@@ -495,7 +490,7 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
else
plen = Encoding::write_immediate_assignment(&m_bts, immediate_assignment, 0, ra,
Fn, tbf->ta, tbf->trx->arfcn, tbf->first_ts, tbf->tsc(),
- tbf->tfi(), tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0, 0,
+ tbf->tfi(), tbf->m_usf[tbf->first_ts], 0, 0, 0, 0,
m_bts.alpha, m_bts.gamma, -1);
pcu_l1if_tx_agch(immediate_assignment, plen);
bitvec_free(immediate_assignment);
@@ -505,11 +500,11 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
/* depending on the current TBF, we assign on PACCH or AGCH */
void BTS::trigger_dl_ass(
- struct gprs_rlcmac_tbf *tbf,
+ struct gprs_rlcmac_dl_tbf *dl_tbf,
struct gprs_rlcmac_tbf *old_tbf, const char *imsi)
{
/* stop pending timer */
- tbf->stop_timer();
+ dl_tbf->stop_timer();
/* check for downlink tbf: */
if (old_tbf) {
@@ -517,27 +512,27 @@ void BTS::trigger_dl_ass(
"PACCH, because %s exists\n", tbf_name(old_tbf));
old_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
/* use TA from old TBF */
- tbf->ta = old_tbf->ta;
- tbf->was_releasing = tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE);
+ dl_tbf->ta = old_tbf->ta;
+ dl_tbf->was_releasing = dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE);
/* change state */
- tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
- tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
+ tbf_new_state(dl_tbf, GPRS_RLCMAC_ASSIGN);
+ dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
/* start timer */
- tbf_timer_start(tbf, 0, Tassign_pacch);
+ tbf_timer_start(dl_tbf, 0, Tassign_pacch);
} else {
- LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for %s on PCH, no TBF exist (IMSI=%s)\n", tbf_name(tbf), imsi);
+ LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for %s on PCH, no TBF exist (IMSI=%s)\n", tbf_name(dl_tbf), imsi);
if (!imsi || strlen(imsi) < 3) {
LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI!\n");
return;
}
- tbf->was_releasing = tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE);
+ dl_tbf->was_releasing = dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE);
/* change state */
- tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
- tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
- tbf->assign_imsi(imsi);
+ tbf_new_state(dl_tbf, GPRS_RLCMAC_ASSIGN);
+ dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH);
+ dl_tbf->assign_imsi(imsi);
/* send immediate assignment */
- tbf->bts->snd_dl_ass(tbf, 0, imsi);
- tbf->dir.dl.wait_confirm = 1;
+ dl_tbf->bts->snd_dl_ass(dl_tbf, 0, imsi);
+ dl_tbf->m_wait_confirm = 1;
}
}
@@ -823,7 +818,7 @@ void gprs_rlcmac_pdch::rcv_control_ack(Packet_Control_Acknowledgement_t *packet,
void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_nack, uint32_t fn)
{
int8_t tfi = 0; /* must be signed */
- struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_dl_tbf *tbf;
int rc;
tfi = ack_nack->DOWNLINK_TFI;
@@ -1049,7 +1044,6 @@ gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_l
struct llist_pods *lpods;
llist_pods_for_each_entry(tbf, tbf_list, list, lpods) {
- OSMO_ASSERT(tbf->direction == dir);
if (tbf->tfi() != tfi)
continue;
if (!tbf->pdch[ts_no])
diff --git a/src/bts.h b/src/bts.h
index 8f99942d..e8459957 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -205,7 +205,7 @@ public:
int rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn);
int rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta);
- void trigger_dl_ass(gprs_rlcmac_tbf *tbf, gprs_rlcmac_tbf *old_tbf, const char *imsi);
+ void trigger_dl_ass(gprs_rlcmac_dl_tbf *tbf, gprs_rlcmac_tbf *old_tbf, const char *imsi);
void snd_dl_ass(gprs_rlcmac_tbf *tbf, uint8_t poll, const char *imsi);
/*
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 13848aa8..ffd61080 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -166,7 +166,7 @@ void Encoding::write_packet_uplink_assignment(
struct gprs_rlcmac_bts *bts,
bitvec * dest, uint8_t old_tfi,
uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
- struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t alpha,
+ struct gprs_rlcmac_ul_tbf *tbf, uint8_t poll, uint8_t alpha,
uint8_t gamma, int8_t ta_idx)
{
// TODO We should use our implementation of encode RLC/MAC Control messages.
@@ -232,7 +232,7 @@ void Encoding::write_packet_uplink_assignment(
for (ts = 0; ts < 8; ts++) {
if (tbf->pdch[ts]) {
bitvec_write_field(dest, wp,0x1,1); // USF_TN(i): on
- bitvec_write_field(dest, wp,tbf->dir.ul.usf[ts],3); // USF_TN(i)
+ bitvec_write_field(dest, wp,tbf->m_usf[ts],3); // USF_TN(i)
if (alpha || gamma)
bitvec_write_field(dest, wp,gamma,5); // GAMMA power control parameter
} else
@@ -375,14 +375,14 @@ void Encoding::encode_rbb(const char *show_rbb, uint8_t *rbb)
/* generate uplink ack */
void Encoding::write_packet_uplink_ack(struct gprs_rlcmac_bts *bts,
- RlcMacDownlink_t * block, struct gprs_rlcmac_tbf *tbf,
+ RlcMacDownlink_t * block, struct gprs_rlcmac_ul_tbf *tbf,
uint8_t final)
{
// Packet Uplink Ack/Nack TS 44.060 11.2.28
char rbb[65];
- tbf->dir.ul.window.update_rbb(rbb);
+ tbf->m_window.update_rbb(rbb);
LOGP(DRLCMACUL, LOGL_DEBUG, "Encoding Ack/Nack for %s "
"(final=%d)\n", tbf_name(tbf), final);
@@ -399,7 +399,7 @@ void Encoding::write_packet_uplink_ack(struct gprs_rlcmac_bts *bts,
block->u.Packet_Uplink_Ack_Nack.UnionType = 0x0; // PU_AckNack_GPRS = on
block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.CHANNEL_CODING_COMMAND = bts->initial_cs_ul - 1; // CS1
block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.FINAL_ACK_INDICATION = final; // FINAL ACK INDICATION
- block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER = tbf->dir.ul.window.ssn(); // STARTING_SEQUENCE_NUMBER
+ block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.STARTING_SEQUENCE_NUMBER = tbf->m_window.ssn(); // STARTING_SEQUENCE_NUMBER
encode_rbb(rbb, block->u.Packet_Uplink_Ack_Nack.u.PU_AckNack_GPRS_Struct.Ack_Nack_Description.RECEIVED_BLOCK_BITMAP);
diff --git a/src/encoding.h b/src/encoding.h
index e62c2c8f..0004c42b 100644
--- a/src/encoding.h
+++ b/src/encoding.h
@@ -47,7 +47,7 @@ public:
struct gprs_rlcmac_bts *bts,
bitvec * dest, uint8_t old_tfi,
uint8_t old_downlink, uint32_t tlli, uint8_t use_tlli,
- struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t alpha,
+ struct gprs_rlcmac_ul_tbf *tbf, uint8_t poll, uint8_t alpha,
uint8_t gamma, int8_t ta_idx);
static void write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_t old_tfi,
@@ -56,7 +56,7 @@ public:
static void encode_rbb(const char *show_rbb, uint8_t *rbb);
- static void write_packet_uplink_ack(struct gprs_rlcmac_bts *bts, RlcMacDownlink_t * block, struct gprs_rlcmac_tbf *tbf,
+ static void write_packet_uplink_ack(struct gprs_rlcmac_bts *bts, RlcMacDownlink_t * block, struct gprs_rlcmac_ul_tbf *tbf,
uint8_t final);
static int write_paging_request(bitvec * dest, uint8_t *ptmsi, uint16_t ptmsi_len);
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 6c5d72c3..0782dbf9 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -152,7 +152,7 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
LOGP(DBSSGP, LOGL_INFO, "LLC [SGSN -> PCU] = TLLI: 0x%08x IMSI: %s len: %d\n", tlli, imsi, len);
- return gprs_rlcmac_tbf::handle(the_pcu.bts, tlli, imsi, ms_class, delay_csec, data, len);
+ return gprs_rlcmac_dl_tbf::handle(the_pcu.bts, tlli, imsi, ms_class, delay_csec, data, len);
}
int gprs_bssgp_pcu_rx_paging_ps(struct msgb *msg, struct tlv_parsed *tp)
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp
index dab38d83..40a183b4 100644
--- a/src/gprs_rlcmac_sched.cpp
+++ b/src/gprs_rlcmac_sched.cpp
@@ -28,9 +28,10 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts,
struct gprs_rlcmac_tbf **poll_tbf,
struct gprs_rlcmac_tbf **ul_ass_tbf,
struct gprs_rlcmac_tbf **dl_ass_tbf,
- struct gprs_rlcmac_tbf **ul_ack_tbf)
+ struct gprs_rlcmac_ul_tbf **ul_ack_tbf)
{
- struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_ul_tbf *ul_tbf;
+ struct gprs_rlcmac_dl_tbf *dl_tbf;
struct llist_pods *lpods;
uint32_t poll_fn;
@@ -39,34 +40,34 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts,
if ((block_nr % 3) == 2)
poll_fn ++;
poll_fn = poll_fn % 2715648;
- llist_pods_for_each_entry(tbf, &bts->ul_tbfs, list, lpods) {
+ llist_pods_for_each_entry(ul_tbf, &bts->ul_tbfs, list, lpods) {
/* this trx, this ts */
- if (tbf->trx->trx_no != trx || tbf->control_ts != ts)
+ if (ul_tbf->trx->trx_no != trx || ul_tbf->control_ts != ts)
continue;
/* polling for next uplink block */
- if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
- && tbf->poll_fn == poll_fn)
- *poll_tbf = tbf;
- if (tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_SEND_ACK)
- *ul_ack_tbf = tbf;
- if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_SEND_ASS)
- *dl_ass_tbf = tbf;
- if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS)
- *ul_ass_tbf = tbf;
+ if (ul_tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
+ && ul_tbf->poll_fn == poll_fn)
+ *poll_tbf = ul_tbf;
+ if (ul_tbf->ul_ack_state == GPRS_RLCMAC_UL_ACK_SEND_ACK)
+ *ul_ack_tbf = ul_tbf;
+ if (ul_tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_SEND_ASS)
+ *dl_ass_tbf = ul_tbf;
+ if (ul_tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS)
+ *ul_ass_tbf = ul_tbf;
#warning "Is this supposed to be fair? The last TBF for each wins? Maybe use llist_add_tail and skip once we have all states?"
}
- llist_pods_for_each_entry(tbf, &bts->dl_tbfs, list, lpods) {
+ llist_pods_for_each_entry(dl_tbf, &bts->dl_tbfs, list, lpods) {
/* this trx, this ts */
- if (tbf->trx->trx_no != trx || tbf->control_ts != ts)
+ if (dl_tbf->trx->trx_no != trx || dl_tbf->control_ts != ts)
continue;
/* polling for next uplink block */
- if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
- && tbf->poll_fn == poll_fn)
- *poll_tbf = tbf;
- if (tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_SEND_ASS)
- *dl_ass_tbf = tbf;
- if (tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS)
- *ul_ass_tbf = tbf;
+ if (dl_tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
+ && dl_tbf->poll_fn == poll_fn)
+ *poll_tbf = dl_tbf;
+ if (dl_tbf->dl_ass_state == GPRS_RLCMAC_DL_ASS_SEND_ASS)
+ *dl_ass_tbf = dl_tbf;
+ if (dl_tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS)
+ *ul_ass_tbf = dl_tbf;
}
return poll_fn;
@@ -75,7 +76,7 @@ static uint32_t sched_poll(struct gprs_rlcmac_bts *bts,
static uint8_t sched_select_uplink(uint8_t trx, uint8_t ts, uint32_t fn,
uint8_t block_nr, struct gprs_rlcmac_pdch *pdch)
{
- struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_ul_tbf *tbf;
uint8_t usf = 0x07;
uint8_t i, tfi;
@@ -94,7 +95,7 @@ static uint8_t sched_select_uplink(uint8_t trx, uint8_t ts, uint32_t fn,
continue;
/* use this USF */
- usf = tbf->dir.ul.usf[ts];
+ usf = tbf->m_usf[ts];
LOGP(DRLCMACSCHED, LOGL_DEBUG, "Received RTS for PDCH: TRX=%d "
"TS=%d FN=%d block_nr=%d scheduling USF=%d for "
"required uplink resource of UL TFI=%d\n", trx, ts, fn,
@@ -112,7 +113,7 @@ static struct msgb *sched_select_ctrl_msg(
uint8_t block_nr, struct gprs_rlcmac_pdch *pdch,
struct gprs_rlcmac_tbf *ul_ass_tbf,
struct gprs_rlcmac_tbf *dl_ass_tbf,
- struct gprs_rlcmac_tbf *ul_ack_tbf)
+ struct gprs_rlcmac_ul_tbf *ul_ack_tbf)
{
struct msgb *msg = NULL;
struct gprs_rlcmac_tbf *tbf = NULL;
@@ -124,11 +125,13 @@ static struct msgb *sched_select_ctrl_msg(
continue;
if (tbf == ul_ass_tbf)
- msg = tbf->create_ul_ass(fn);
+ msg = ul_ass_tbf->create_ul_ass(fn);
else if (tbf == dl_ass_tbf)
- msg = tbf->create_dl_ass(fn);
+ msg = dl_ass_tbf->create_dl_ass(fn);
+ else if (tbf == ul_ack_tbf)
+ msg = ul_ack_tbf->create_ul_ack(fn);
else
- msg = tbf->create_ul_ack(fn);
+ abort();
if (!msg) {
tbf = NULL;
@@ -164,7 +167,7 @@ static struct msgb *sched_select_downlink(struct gprs_rlcmac_bts *bts,
uint8_t block_nr, struct gprs_rlcmac_pdch *pdch)
{
struct msgb *msg = NULL;
- struct gprs_rlcmac_tbf *tbf = NULL;
+ struct gprs_rlcmac_dl_tbf *tbf = NULL;
uint8_t i, tfi;
/* select downlink resource */
@@ -183,7 +186,7 @@ static struct msgb *sched_select_downlink(struct gprs_rlcmac_bts *bts,
continue;
/* waiting for CCCH IMM.ASS confirm */
- if (tbf->dir.dl.wait_confirm)
+ if (tbf->m_wait_confirm)
continue;
LOGP(DRLCMACSCHED, LOGL_DEBUG, "Scheduling data message at "
@@ -224,7 +227,8 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
{
struct gprs_rlcmac_pdch *pdch;
struct gprs_rlcmac_tbf *poll_tbf = NULL, *dl_ass_tbf = NULL,
- *ul_ass_tbf = NULL, *ul_ack_tbf = NULL;
+ *ul_ass_tbf = NULL;
+ struct gprs_rlcmac_ul_tbf *ul_ack_tbf = NULL;
uint8_t usf = 0x7;
struct msgb *msg = NULL;
uint32_t poll_fn, sba_fn;
diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp
index b070c2e9..27b01d79 100644
--- a/src/gprs_rlcmac_ts_alloc.cpp
+++ b/src/gprs_rlcmac_ts_alloc.cpp
@@ -77,7 +77,7 @@ static const struct gprs_ms_multislot_class gprs_ms_multislot_class[32] = {
static inline int8_t find_free_usf(struct gprs_rlcmac_pdch *pdch)
{
- struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_ul_tbf *tbf;
uint8_t usf_map = 0;
uint8_t tfi, usf;
@@ -86,7 +86,7 @@ static inline int8_t find_free_usf(struct gprs_rlcmac_pdch *pdch)
tbf = pdch->ul_tbf_by_tfi(tfi);
if (!tbf)
continue;
- usf_map |= (1 << tbf->dir.ul.usf[pdch->ts_no]);
+ usf_map |= (1 << tbf->m_usf[pdch->ts_no]);
}
/* look for USF, don't use USF=7 */
@@ -118,16 +118,16 @@ static int find_enabled_pdch(struct gprs_rlcmac_trx *trx, const uint8_t start_ts
static void assign_uplink_tbf_usf(
struct gprs_rlcmac_pdch *pdch,
- struct gprs_rlcmac_tbf *tbf, int8_t usf)
+ struct gprs_rlcmac_ul_tbf *tbf, int8_t usf)
{
tbf->trx->ul_tbf[tbf->tfi()] = tbf;
tbf->pdch[pdch->ts_no] = pdch;
- tbf->dir.ul.usf[pdch->ts_no] = usf;
+ tbf->m_usf[pdch->ts_no] = usf;
}
static void assign_dlink_tbf(
struct gprs_rlcmac_pdch *pdch,
- struct gprs_rlcmac_tbf *tbf)
+ struct gprs_rlcmac_dl_tbf *tbf)
{
tbf->trx->dl_tbf[tbf->tfi()] = tbf;
tbf->pdch[pdch->ts_no] = pdch;
@@ -155,6 +155,7 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
pdch = &tbf->trx->pdch[ts];
if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
int8_t usf; /* must be signed */
+ struct gprs_rlcmac_ul_tbf *ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf);
/* if USF available */
usf = find_free_usf(pdch);
@@ -165,10 +166,11 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
}
LOGP(DRLCMAC, LOGL_DEBUG, "- Assign uplink "
"TS=%d USF=%d\n", ts, usf);
- assign_uplink_tbf_usf(pdch, tbf, usf);
+ assign_uplink_tbf_usf(pdch, ul_tbf, usf);
} else {
+ struct gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(tbf);
LOGP(DRLCMAC, LOGL_DEBUG, "- Assign downlink TS=%d\n", ts);
- assign_dlink_tbf(pdch, tbf);
+ assign_dlink_tbf(pdch, dl_tbf);
}
/* the only one TS is the common TS */
tbf->first_ts = tbf->first_common_ts = ts;
@@ -627,6 +629,7 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
}
if (tbf->direction == GPRS_RLCMAC_DL_TBF) {
+ struct gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(tbf);
/* assign downlink */
if (rx_window == 0) {
LOGP(DRLCMAC, LOGL_NOTICE, "No downlink slots "
@@ -642,23 +645,24 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
continue;
LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning DL TS "
"%d\n", ts);
- assign_dlink_tbf(&tbf->trx->pdch[ts], tbf);
+ assign_dlink_tbf(&tbf->trx->pdch[ts], dl_tbf);
slotcount++;
if (slotcount == 1)
- tbf->first_ts = ts;
+ dl_tbf->first_ts = ts;
if (single)
break;
}
}
} else {
+ struct gprs_rlcmac_ul_tbf *ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf);
for (ts = 0; ts < 8; ts++) {
if ((tx_window & (1 << ts))) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning UL TS "
"%d\n", ts);
- assign_uplink_tbf_usf(&tbf->trx->pdch[ts], tbf, usf[ts]);
+ assign_uplink_tbf_usf(&tbf->trx->pdch[ts], ul_tbf, usf[ts]);
slotcount++;
if (slotcount == 1)
- tbf->first_ts = ts;
+ ul_tbf->first_ts = ts;
if (single)
break;
}
diff --git a/src/poll_controller.cpp b/src/poll_controller.cpp
index dea75edf..7e1aa787 100644
--- a/src/poll_controller.cpp
+++ b/src/poll_controller.cpp
@@ -31,26 +31,27 @@ PollController::PollController(BTS& bts)
void PollController::expireTimedout(int frame_number)
{
struct gprs_rlcmac_bts *bts = m_bts.bts_data();
- struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_dl_tbf *dl_tbf;
+ struct gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_sba *sba, *sba2;
struct llist_pods *lpods;
uint32_t elapsed;
/* check for poll timeout */
- llist_pods_for_each_entry(tbf, &bts->ul_tbfs, list, lpods) {
- if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) {
- elapsed = (frame_number + 2715648 - tbf->poll_fn)
+ llist_pods_for_each_entry(ul_tbf, &bts->ul_tbfs, list, lpods) {
+ if (ul_tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) {
+ elapsed = (frame_number + 2715648 - ul_tbf->poll_fn)
% 2715648;
if (elapsed >= 20 && elapsed < 2715400)
- tbf->poll_timeout();
+ ul_tbf->poll_timeout();
}
}
- llist_pods_for_each_entry(tbf, &bts->dl_tbfs, list, lpods) {
- if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) {
- elapsed = (frame_number + 2715648 - tbf->poll_fn)
+ llist_pods_for_each_entry(dl_tbf, &bts->dl_tbfs, list, lpods) {
+ if (dl_tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) {
+ elapsed = (frame_number + 2715648 - dl_tbf->poll_fn)
% 2715648;
if (elapsed >= 20 && elapsed < 2715400)
- tbf->poll_timeout();
+ dl_tbf->poll_timeout();
}
}
llist_for_each_entry_safe(sba, sba2, &m_bts.sba()->m_sbas, list) {
diff --git a/src/rlc.cpp b/src/rlc.cpp
index 36320dc9..42b602cb 100644
--- a/src/rlc.cpp
+++ b/src/rlc.cpp
@@ -46,6 +46,13 @@ void gprs_rlc_v_b::reset()
mark_invalid(i);
}
+void gprs_rlc_dl_window::reset()
+{
+ m_v_s = 0;
+ m_v_a = 0;
+ m_v_b.reset();
+}
+
int gprs_rlc_dl_window::resend_needed()
{
for (uint16_t bsn = v_a(); bsn != v_s(); bsn = (bsn + 1) & mod_sns()) {
diff --git a/src/rlc.h b/src/rlc.h
index 7bea8a1c..55cae3ff 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -109,6 +109,7 @@ private:
* most simple form of inheritance is not a POD anymore.
*/
struct gprs_rlc_dl_window {
+ void reset();
const uint16_t mod_sns() const;
const uint16_t sns() const;
const uint16_t ws() const;
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 22570185..22b8ce0e 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -78,14 +78,14 @@ void gprs_rlcmac_tbf::assign_imsi(const char *imsi)
m_imsi[sizeof(m_imsi) - 1] = '\0';
}
-static struct gprs_rlcmac_tbf *tbf_lookup_dl(BTS *bts,
+static struct gprs_rlcmac_dl_tbf *tbf_lookup_dl(BTS *bts,
const uint32_t tlli, const char *imsi)
{
/* TODO: look up by IMSI first, then tlli, then old_tlli */
return bts->dl_tbf_by_tlli(tlli);
}
-int gprs_rlcmac_tbf::append_data(const uint8_t ms_class,
+int gprs_rlcmac_dl_tbf::append_data(const uint8_t ms_class,
const uint16_t pdu_delay_csec,
const uint8_t *data, const uint16_t len)
{
@@ -123,25 +123,26 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts,
{
uint8_t trx, ta, ss;
int8_t use_trx;
- struct gprs_rlcmac_tbf *old_tbf, *tbf;
+ struct gprs_rlcmac_ul_tbf *ul_tbf, *old_ul_tbf;
+ struct gprs_rlcmac_dl_tbf *dl_tbf;
int8_t tfi; /* must be signed */
int rc;
/* check for uplink data, so we copy our informations */
#warning "Do the same look up for IMSI, TLLI and OLD_TLLI"
#warning "Refactor the below lines... into a new method"
- tbf = bts->bts->ul_tbf_by_tlli(tlli);
- if (tbf && tbf->dir.ul.contention_resolution_done
- && !tbf->dir.ul.final_ack_sent) {
- use_trx = tbf->trx->trx_no;
- ta = tbf->ta;
+ ul_tbf = bts->bts->ul_tbf_by_tlli(tlli);
+ if (ul_tbf && ul_tbf->m_contention_resolution_done
+ && !ul_tbf->m_final_ack_sent) {
+ use_trx = ul_tbf->trx->trx_no;
+ ta = ul_tbf->ta;
ss = 0;
- old_tbf = tbf;
+ old_ul_tbf = ul_tbf;
} else {
use_trx = -1;
/* we already have an uplink TBF, so we use that TA */
- if (tbf)
- ta = tbf->ta;
+ if (ul_tbf)
+ ta = ul_tbf->ta;
else {
/* recall TA */
rc = bts->bts->timing_advance()->recall(tlli);
@@ -153,7 +154,7 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts,
ta = rc;
}
ss = 1; /* PCH assignment only allows one timeslot */
- old_tbf = NULL;
+ old_ul_tbf = NULL;
}
// Create new TBF (any TRX)
@@ -165,49 +166,49 @@ static int tbf_new_dl_assignment(struct gprs_rlcmac_bts *bts,
return -EBUSY;
}
/* set number of downlink slots according to multislot class */
- tbf = tbf_alloc_dl_tbf(bts, tbf, tfi, trx, ms_class, ss);
- if (!tbf) {
+ dl_tbf = tbf_alloc_dl_tbf(bts, ul_tbf, tfi, trx, ms_class, ss);
+ if (!dl_tbf) {
LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
/* FIXME: send reject */
return -EBUSY;
}
- tbf->m_tlli = tlli;
- tbf->m_tlli_valid = 1;
- tbf->ta = ta;
+ dl_tbf->m_tlli = tlli;
+ dl_tbf->m_tlli_valid = 1;
+ dl_tbf->ta = ta;
- LOGP(DRLCMAC, LOGL_DEBUG, "%s [DOWNLINK] START\n", tbf_name(tbf));
+ LOGP(DRLCMAC, LOGL_DEBUG, "%s [DOWNLINK] START\n", tbf_name(dl_tbf));
/* new TBF, so put first frame */
- tbf->m_llc.put_frame(data, len);
- tbf->bts->llc_frame_sched();
+ dl_tbf->m_llc.put_frame(data, len);
+ dl_tbf->bts->llc_frame_sched();
/* Store IMSI for later look-up and PCH retransmission */
- tbf->assign_imsi(imsi);
+ dl_tbf->assign_imsi(imsi);
/* trigger downlink assignment and set state to ASSIGN.
* we don't use old_downlink, so the possible uplink is used
* to trigger downlink assignment. if there is no uplink,
* AGCH is used. */
- tbf->bts->trigger_dl_ass(tbf, old_tbf, imsi);
+ dl_tbf->bts->trigger_dl_ass(dl_tbf, old_ul_tbf, imsi);
return 0;
}
/**
* TODO: split into unit test-able parts...
*/
-int gprs_rlcmac_tbf::handle(struct gprs_rlcmac_bts *bts,
+int gprs_rlcmac_dl_tbf::handle(struct gprs_rlcmac_bts *bts,
const uint32_t tlli, const char *imsi,
const uint8_t ms_class, const uint16_t delay_csec,
const uint8_t *data, const uint16_t len)
{
- struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_dl_tbf *dl_tbf;
/* check for existing TBF */
- tbf = tbf_lookup_dl(bts->bts, tlli, imsi);
- if (tbf) {
- int rc = tbf->append_data(ms_class, delay_csec, data, len);
+ dl_tbf = tbf_lookup_dl(bts->bts, tlli, imsi);
+ if (dl_tbf) {
+ int rc = dl_tbf->append_data(ms_class, delay_csec, data, len);
if (rc >= 0)
- tbf->assign_imsi(imsi);
+ dl_tbf->assign_imsi(imsi);
return rc;
}
@@ -239,7 +240,7 @@ gprs_rlcmac_ul_tbf *tbf_alloc_ul(struct gprs_rlcmac_bts *bts,
}
tbf->m_tlli = tlli;
tbf->m_tlli_valid = 1; /* no contention resolution */
- tbf->dir.ul.contention_resolution_done = 1;
+ tbf->m_contention_resolution_done = 1;
tbf->ta = ta; /* use current TA */
tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN);
tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
@@ -403,16 +404,17 @@ void gprs_rlcmac_tbf::poll_timeout()
}
ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
if (state_is(GPRS_RLCMAC_FINISHED)) {
- dir.ul.n3103++;
- if (dir.ul.n3103 == bts->bts_data()->n3103) {
+ gprs_rlcmac_ul_tbf *ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(this);
+ ul_tbf->m_n3103++;
+ if (ul_tbf->m_n3103 == ul_tbf->bts->bts_data()->n3103) {
LOGP(DRLCMAC, LOGL_NOTICE,
"- N3103 exceeded\n");
- tbf_new_state(this, GPRS_RLCMAC_RELEASING);
- tbf_timer_start(this, 3169, bts->bts_data()->t3169, 0);
+ tbf_new_state(ul_tbf, GPRS_RLCMAC_RELEASING);
+ tbf_timer_start(ul_tbf, 3169, ul_tbf->bts->bts_data()->t3169, 0);
return;
}
/* reschedule UL ack */
- ul_ack_state = GPRS_RLCMAC_UL_ACK_SEND_ACK;
+ ul_tbf->ul_ack_state = GPRS_RLCMAC_UL_ACK_SEND_ACK;
}
} else if (ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK) {
if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_TO_UL_ASS))) {
@@ -451,29 +453,31 @@ void gprs_rlcmac_tbf::poll_timeout()
/* reschedule DL assignment */
dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS;
} else if (direction == GPRS_RLCMAC_DL_TBF) {
- if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
+ gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(this);
+
+ if (!(dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK))) {
LOGP(DRLCMAC, LOGL_NOTICE, "- Timeout for polling "
"PACKET DOWNLINK ACK.\n");
- rlcmac_diag();
- state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
+ dl_tbf->rlcmac_diag();
+ dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
}
- n3105++;
- if (n3105 == bts->bts_data()->n3105) {
+ dl_tbf->n3105++;
+ if (dl_tbf->n3105 == dl_tbf->bts->bts_data()->n3105) {
LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
- tbf_new_state(this, GPRS_RLCMAC_RELEASING);
- tbf_timer_start(this, 3195, bts_data()->t3195, 0);
+ tbf_new_state(dl_tbf, GPRS_RLCMAC_RELEASING);
+ tbf_timer_start(dl_tbf, 3195, dl_tbf->bts_data()->t3195, 0);
return;
}
/* resend IMM.ASS on CCCH on timeout */
- if ((state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
- && !(state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) {
+ if ((dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))
+ && !(dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_DL_ACK))) {
LOGP(DRLCMAC, LOGL_DEBUG, "Re-send dowlink assignment "
"for %s on PCH (IMSI=%s)\n",
- tbf_name(this),
+ tbf_name(dl_tbf),
m_imsi);
/* send immediate assignment */
- bts->snd_dl_ass(this, 0, m_imsi);
- dir.dl.wait_confirm = 1;
+ dl_tbf->bts->snd_dl_ass(dl_tbf, 0, m_imsi);
+ dl_tbf->m_wait_confirm = 1;
}
} else
LOGP(DRLCMAC, LOGL_ERROR, "- Poll Timeout, but no event!\n");
@@ -616,14 +620,15 @@ void gprs_rlcmac_tbf::handle_timeout()
"in assign state\n", tbf_name(this));
}
if ((state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) {
- dir.dl.wait_confirm = 0;
- if (state_is(GPRS_RLCMAC_ASSIGN)) {
- tbf_assign_control_ts(this);
+ gprs_rlcmac_dl_tbf *dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(this);
+ dl_tbf->m_wait_confirm = 0;
+ if (dl_tbf->state_is(GPRS_RLCMAC_ASSIGN)) {
+ tbf_assign_control_ts(dl_tbf);
- if (!upgrade_to_multislot) {
+ if (!dl_tbf->upgrade_to_multislot) {
/* change state to FLOW, so scheduler
* will start transmission */
- tbf_new_state(this, GPRS_RLCMAC_FLOW);
+ tbf_new_state(dl_tbf, GPRS_RLCMAC_FLOW);
break;
}
@@ -633,15 +638,15 @@ void gprs_rlcmac_tbf::handle_timeout()
* PDCH. */
/* keep to flags */
- state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
- state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
+ dl_tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
+ dl_tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
- update();
+ dl_tbf->update();
- bts->trigger_dl_ass(this, this, NULL);
+ dl_tbf->bts->trigger_dl_ass(dl_tbf, dl_tbf, NULL);
} else
LOGP(DRLCMAC, LOGL_NOTICE, "%s Continue flow after "
- "IMM.ASS confirm\n", tbf_name(this));
+ "IMM.ASS confirm\n", tbf_name(dl_tbf));
}
break;
case 3169:
@@ -889,19 +894,19 @@ int gprs_rlcmac_tbf::assemble_forward_llc(const gprs_rlc_data *_data)
* Create DL data block
* The messages are fragmented and forwarded as data blocks.
*/
-struct msgb *gprs_rlcmac_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts)
+struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts)
{
LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink (V(A)==%d .. "
"V(S)==%d)\n", tbf_name(this),
- dir.dl.window.v_a(), dir.dl.window.v_s());
+ m_window.v_a(), m_window.v_s());
do_resend:
/* check if there is a block with negative acknowledgement */
- int resend_bsn = dir.dl.window.resend_needed();
+ int resend_bsn = m_window.resend_needed();
if (resend_bsn >= 0) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n", resend_bsn);
/* re-send block with negative aknowlegement */
- dir.dl.window.m_v_b.mark_unacked(resend_bsn);
+ m_window.m_v_b.mark_unacked(resend_bsn);
bts->rlc_resent();
return create_dl_acked_block(fn, ts, resend_bsn, false);
}
@@ -912,12 +917,12 @@ do_resend:
if (state_is(GPRS_RLCMAC_FINISHED)) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- Restarting at BSN %d, "
"because all blocks have been transmitted.\n",
- dir.dl.window.v_a());
+ m_window.v_a());
bts->rlc_restarted();
} else {
LOGP(DRLCMACDL, LOGL_NOTICE, "- Restarting at BSN %d, "
"because all window is stalled.\n",
- dir.dl.window.v_a());
+ m_window.v_a());
bts->rlc_stalled();
}
/* If V(S) == V(A) and finished state, we would have received
@@ -926,17 +931,17 @@ do_resend:
* from MS. But in this case we did not receive the final ack
* indication from MS. This should never happen if MS works
* correctly. */
- if (dir.dl.window.window_empty()) {
+ if (m_window.window_empty()) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- MS acked all blocks, "
"so we re-transmit final block!\n");
/* we just send final block again */
- int16_t index = dir.dl.window.v_s_mod(-1);
+ int16_t index = m_window.v_s_mod(-1);
bts->rlc_resent();
return create_dl_acked_block(fn, ts, index, false);
}
/* cycle through all unacked blocks */
- int resend = dir.dl.window.mark_for_resend();
+ int resend = m_window.mark_for_resend();
/* At this point there should be at least one unacked block
* to be resent. If not, this is an software error. */
@@ -945,7 +950,7 @@ do_resend:
"There are no unacknowledged blocks, but V(A) "
" != V(S). PLEASE FIX!\n");
/* we just send final block again */
- int16_t index = dir.dl.window.v_s_mod(-1);
+ int16_t index = m_window.v_s_mod(-1);
return create_dl_acked_block(fn, ts, index, false);
}
goto do_resend;
@@ -954,7 +959,7 @@ do_resend:
return create_new_bsn(fn, ts);
}
-struct msgb *gprs_rlcmac_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts)
+struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts)
{
struct rlc_dl_header *rh;
struct rlc_li_field *li;
@@ -963,10 +968,10 @@ struct msgb *gprs_rlcmac_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts
uint16_t space, chunk;
gprs_rlc_data *rlc_data;
bool first_fin_ack = false;
- const uint16_t bsn = dir.dl.window.v_s();
+ const uint16_t bsn = m_window.v_s();
LOGP(DRLCMACDL, LOGL_DEBUG, "- Sending new block at BSN %d\n",
- dir.dl.window.v_s());
+ m_window.v_s());
#warning "Selection of the CS doesn't belong here"
if (cs == 0) {
@@ -1115,13 +1120,13 @@ struct msgb *gprs_rlcmac_tbf::create_new_bsn(const uint32_t fn, const uint8_t ts
#warning "move this up?"
rlc_data->len = block_length;
/* raise send state and set ack state array */
- dir.dl.window.m_v_b.mark_unacked(bsn);
- dir.dl.window.increment_send();
+ m_window.m_v_b.mark_unacked(bsn);
+ m_window.increment_send();
return create_dl_acked_block(fn, ts, bsn, first_fin_ack);
}
-struct msgb *gprs_rlcmac_tbf::create_dl_acked_block(
+struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
const uint32_t fn, const uint8_t ts,
const int index, const bool first_fin_ack)
{
@@ -1140,7 +1145,7 @@ struct msgb *gprs_rlcmac_tbf::create_dl_acked_block(
/* poll after POLL_ACK_AFTER_FRAMES frames, or when final block is tx.
*/
- if (dir.dl.tx_counter >= POLL_ACK_AFTER_FRAMES || first_fin_ack) {
+ if (m_tx_counter >= POLL_ACK_AFTER_FRAMES || first_fin_ack) {
if (first_fin_ack) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
"polling, because first final block sent.\n");
@@ -1166,7 +1171,7 @@ struct msgb *gprs_rlcmac_tbf::create_dl_acked_block(
else {
LOGP(DRLCMACDL, LOGL_DEBUG, "Polling sheduled in this "
"TS %d\n", ts);
- dir.dl.tx_counter = 0;
+ m_tx_counter = 0;
/* start timer whenever we send the final block */
if (rh->fbi == 1)
tbf_timer_start(this, 3191, bts_data()->t3191, 0);
@@ -1187,7 +1192,7 @@ struct msgb *gprs_rlcmac_tbf::create_dl_acked_block(
return NULL;
/* Increment TX-counter */
- dir.dl.tx_counter++;
+ m_tx_counter++;
memcpy(msgb_put(dl_msg, len), data, len);
bts->rlc_sent();
@@ -1198,7 +1203,7 @@ struct msgb *gprs_rlcmac_tbf::create_dl_acked_block(
struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
{
struct msgb *msg;
- struct gprs_rlcmac_tbf *new_tbf;
+ struct gprs_rlcmac_dl_tbf *new_dl_tbf;
int poll_ass_dl = 1;
if (direction == GPRS_RLCMAC_DL_TBF && control_ts != first_common_ts) {
@@ -1224,19 +1229,21 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
/* on uplink TBF we get the downlink TBF to be assigned. */
if (direction == GPRS_RLCMAC_UL_TBF) {
+ gprs_rlcmac_ul_tbf *ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(this);
+
/* be sure to check first, if contention resolution is done,
* otherwise we cannot send the assignment yet */
- if (!dir.ul.contention_resolution_done) {
+ if (!ul_tbf->m_contention_resolution_done) {
LOGP(DRLCMAC, LOGL_DEBUG, "Cannot assign DL TBF now, "
"because contention resolution is not "
"finished.\n");
return NULL;
}
#warning "THIS should probably go over the IMSI too"
- new_tbf = bts->dl_tbf_by_tlli(m_tlli);
+ new_dl_tbf = ul_tbf->bts->dl_tbf_by_tlli(m_tlli);
} else
- new_tbf = this;
- if (!new_tbf) {
+ new_dl_tbf = static_cast<gprs_rlcmac_dl_tbf *>(this);
+ if (!new_dl_tbf) {
LOGP(DRLCMACDL, LOGL_ERROR, "We have a schedule for downlink "
"assignment at uplink %s, but there is no downlink "
"TBF\n", tbf_name(this));
@@ -1254,10 +1261,10 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
}
bitvec_unhex(ass_vec,
"2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
- LOGP(DRLCMAC, LOGL_INFO, "%s start Packet Downlink Assignment (PACCH)\n", tbf_name(new_tbf));
+ LOGP(DRLCMAC, LOGL_INFO, "%s start Packet Downlink Assignment (PACCH)\n", tbf_name(new_dl_tbf));
RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
Encoding::write_packet_downlink_assignment(mac_control_block, m_tfi,
- (direction == GPRS_RLCMAC_DL_TBF), new_tbf,
+ (direction == GPRS_RLCMAC_DL_TBF), new_dl_tbf,
poll_ass_dl, bts_data()->alpha, bts_data()->gamma, -1, 0);
LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n");
encode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
@@ -1273,10 +1280,10 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK;
} else {
dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
- tbf_new_state(new_tbf, GPRS_RLCMAC_FLOW);
- tbf_assign_control_ts(new_tbf);
+ tbf_new_state(new_dl_tbf, GPRS_RLCMAC_FLOW);
+ tbf_assign_control_ts(new_dl_tbf);
/* stop pending assignment timer */
- new_tbf->stop_timer();
+ new_dl_tbf->stop_timer();
}
@@ -1286,7 +1293,7 @@ struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn)
struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn)
{
struct msgb *msg;
- struct gprs_rlcmac_tbf *new_tbf;
+ struct gprs_rlcmac_ul_tbf *new_tbf;
if (poll_state != GPRS_RLCMAC_POLL_NONE) {
LOGP(DRLCMACUL, LOGL_DEBUG, "Polling is already "
@@ -1305,7 +1312,7 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn)
if (direction == GPRS_RLCMAC_DL_TBF)
new_tbf = bts->ul_tbf_by_tlli(m_tlli);
else
- new_tbf = this;
+ new_tbf = static_cast<gprs_rlcmac_ul_tbf *>(this);
if (!new_tbf) {
LOGP(DRLCMACUL, LOGL_ERROR, "We have a schedule for uplink "
@@ -1346,7 +1353,7 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn)
return msg;
}
-struct msgb *gprs_rlcmac_tbf::create_ul_ack(uint32_t fn)
+struct msgb *gprs_rlcmac_ul_tbf::create_ul_ack(uint32_t fn)
{
int final = (state_is(GPRS_RLCMAC_FINISHED));
struct msgb *msg;
@@ -1384,27 +1391,27 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ack(uint32_t fn)
/* now we must set this flag, so we are allowed to assign downlink
* TBF on PACCH. it is only allowed when TLLI is acknowledged. */
- dir.ul.contention_resolution_done = 1;
+ m_contention_resolution_done = 1;
if (final) {
poll_state = GPRS_RLCMAC_POLL_SCHED;
poll_fn = (fn + 13) % 2715648;
/* waiting for final acknowledge */
ul_ack_state = GPRS_RLCMAC_UL_ACK_WAIT_ACK;
- dir.ul.final_ack_sent = 1;
+ m_final_ack_sent = 1;
} else
ul_ack_state = GPRS_RLCMAC_UL_ACK_NONE;
return msg;
}
-int gprs_rlcmac_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
+int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
{
int16_t dist; /* must be signed */
uint16_t lost = 0, received = 0;
char show_rbb[65];
char show_v_b[RLC_MAX_SNS + 1];
- const uint16_t mod_sns = dir.dl.window.mod_sns();
+ const uint16_t mod_sns = m_window.mod_sns();
Decoding::extract_rbb(rbb, show_rbb);
/* show received array in debug (bit 64..1) */
@@ -1414,9 +1421,9 @@ int gprs_rlcmac_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
/* apply received array to receive state (SSN-64..SSN-1) */
/* calculate distance of ssn from V(S) */
- dist = (dir.dl.window.v_s() - ssn) & mod_sns;
+ dist = (m_window.v_s() - ssn) & mod_sns;
/* check if distance is less than distance V(A)..V(S) */
- if (dist >= dir.dl.window.distance()) {
+ if (dist >= m_window.distance()) {
/* this might happpen, if the downlink assignment
* was not received by ms and the ack refers
* to previous TBF
@@ -1427,24 +1434,24 @@ int gprs_rlcmac_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
return 1; /* indicate to free TBF */
}
- dir.dl.window.update(bts, show_rbb, ssn,
+ m_window.update(bts, show_rbb, ssn,
&lost, &received);
/* report lost and received packets */
gprs_rlcmac_received_lost(this, received, lost);
/* raise V(A), if possible */
- dir.dl.window.raise(dir.dl.window.move_window());
+ m_window.raise(m_window.move_window());
/* show receive state array in debug (V(A)..V(S)-1) */
- dir.dl.window.show_state(show_v_b);
+ m_window.show_state(show_v_b);
LOGP(DRLCMACDL, LOGL_DEBUG, "- V(B): (V(A)=%d)\"%s\""
"(V(S)-1=%d) A=Acked N=Nacked U=Unacked "
"X=Resend-Unacked I=Invalid\n",
- dir.dl.window.v_a(), show_v_b,
- dir.dl.window.v_s_mod(-1));
+ m_window.v_a(), show_v_b,
+ m_window.v_s_mod(-1));
- if (state_is(GPRS_RLCMAC_FINISHED) && dir.dl.window.window_empty()) {
+ if (state_is(GPRS_RLCMAC_FINISHED) && m_window.window_empty()) {
LOGP(DRLCMACDL, LOGL_NOTICE, "Received acknowledge of "
"all blocks, but without final ack "
"inidcation (don't worry)\n");
@@ -1453,14 +1460,14 @@ int gprs_rlcmac_tbf::update_window(const uint8_t ssn, const uint8_t *rbb)
}
-int gprs_rlcmac_tbf::maybe_start_new_window()
+int gprs_rlcmac_dl_tbf::maybe_start_new_window()
{
struct msgb *msg;
uint16_t received;
LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n");
/* range V(A)..V(S)-1 */
- received = dir.dl.window.count_unacked();
+ received = m_window.count_unacked();
/* report all outstanding packets as received */
gprs_rlcmac_received_lost(this, received, 0);
@@ -1486,7 +1493,7 @@ int gprs_rlcmac_tbf::maybe_start_new_window()
return 0;
}
-int gprs_rlcmac_tbf::rcvd_dl_ack(uint8_t final_ack, uint8_t ssn, uint8_t *rbb)
+int gprs_rlcmac_dl_tbf::rcvd_dl_ack(uint8_t final_ack, uint8_t ssn, uint8_t *rbb)
{
LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink acknowledge\n", tbf_name(this));
@@ -1613,19 +1620,19 @@ int gprs_rlcmac_tbf::extract_tlli(const uint8_t *data, const size_t len)
return 1;
}
-int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len, int8_t rssi)
+int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len, int8_t rssi)
{
struct rlc_ul_header *rh = (struct rlc_ul_header *)data;
int rc;
- const uint16_t mod_sns = dir.ul.window.mod_sns();
- const uint16_t ws = dir.ul.window.ws();
+ const uint16_t mod_sns = m_window.mod_sns();
+ const uint16_t ws = m_window.ws();
this->state_flags |= (1 << GPRS_RLCMAC_FLAG_UL_DATA);
LOGP(DRLCMACUL, LOGL_DEBUG, "UL DATA TFI=%d received (V(Q)=%d .. "
- "V(R)=%d)\n", rh->tfi, this->dir.ul.window.v_q(),
- this->dir.ul.window.v_r());
+ "V(R)=%d)\n", rh->tfi, this->m_window.v_q(),
+ this->m_window.v_r());
/* process RSSI */
gprs_rlcmac_rssi(this, rssi);
@@ -1655,13 +1662,13 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len
tbf_timer_start(this, 3169, bts_data()->t3169, 0);
/* Increment RX-counter */
- this->dir.ul.rx_counter++;
+ this->m_rx_counter++;
- if (!dir.ul.window.is_in_window(rh->bsn)) {
+ if (!m_window.is_in_window(rh->bsn)) {
LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d out of window "
"%d..%d (it's normal)\n", rh->bsn,
- dir.ul.window.v_q(),
- (dir.ul.window.v_q() + ws - 1) & mod_sns);
+ m_window.v_q(),
+ (m_window.v_q() + ws - 1) & mod_sns);
maybe_schedule_uplink_acknack(rh);
return 0;
}
@@ -1669,15 +1676,15 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len
/* Write block to buffer and set receive state array. */
m_rlc.block(rh->bsn)->put_data(data, len);
LOGP(DRLCMACUL, LOGL_DEBUG, "- BSN %d storing in window (%d..%d)\n",
- rh->bsn, dir.ul.window.v_q(),
- (dir.ul.window.v_q() + ws - 1) & mod_sns);
+ rh->bsn, m_window.v_q(),
+ (m_window.v_q() + ws - 1) & mod_sns);
/* Raise V(Q) if possible, and retrieve LLC frames from blocks.
* This is looped until there is a gap (non received block) or
* the window is empty.*/
- const uint16_t v_q_beg = dir.ul.window.v_q();
+ const uint16_t v_q_beg = m_window.v_q();
- const uint16_t count = dir.ul.window.receive_bsn(rh->bsn);
+ const uint16_t count = m_window.receive_bsn(rh->bsn);
/* Retrieve LLC frames from blocks that are ready */
for (uint16_t i = 0; i < count; ++i) {
@@ -1687,9 +1694,9 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len
/* Check CV of last frame in buffer */
if (this->state_is(GPRS_RLCMAC_FLOW) /* still in flow state */
- && this->dir.ul.window.v_q() == this->dir.ul.window.v_r()) { /* if complete */
+ && this->m_window.v_q() == this->m_window.v_r()) { /* if complete */
struct rlc_ul_header *last_rh = (struct rlc_ul_header *)
- m_rlc.block((dir.ul.window.v_r() - 1) & mod_sns)->block;
+ m_rlc.block((m_window.v_r() - 1) & mod_sns)->block;
LOGP(DRLCMACUL, LOGL_DEBUG, "- No gaps in received block, "
"last block: BSN=%d CV=%d\n", last_rh->bsn,
last_rh->cv);
@@ -1698,7 +1705,7 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len
"TBF\n");
tbf_new_state(this, GPRS_RLCMAC_FINISHED);
/* Reset N3103 counter. */
- this->dir.ul.n3103 = 0;
+ this->m_n3103 = 0;
}
}
@@ -1709,10 +1716,10 @@ int gprs_rlcmac_tbf::rcv_data_block_acknowledged(const uint8_t *data, size_t len
return 0;
}
-void gprs_rlcmac_tbf::maybe_schedule_uplink_acknack(const rlc_ul_header *rh)
+void gprs_rlcmac_ul_tbf::maybe_schedule_uplink_acknack(const rlc_ul_header *rh)
{
if (rh->si || rh->ti || state_is(GPRS_RLCMAC_FINISHED)
- || (dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
+ || (m_rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
if (rh->si) {
LOGP(DRLCMACUL, LOGL_NOTICE, "- Scheduling Ack/Nack, "
"because MS is stalled.\n");
@@ -1725,7 +1732,7 @@ void gprs_rlcmac_tbf::maybe_schedule_uplink_acknack(const rlc_ul_header *rh)
LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
"because last block has CV==0.\n");
}
- if ((dir.ul.rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
+ if ((m_rx_counter % SEND_ACK_AFTER_FRAMES) == 0) {
LOGP(DRLCMACUL, LOGL_DEBUG, "- Scheduling Ack/Nack, "
"because %d frames received.\n",
SEND_ACK_AFTER_FRAMES);
@@ -1779,15 +1786,16 @@ const char *tbf_name(gprs_rlcmac_tbf *tbf)
}
-void gprs_rlcmac_tbf::reuse_tbf(const uint8_t *data, const uint16_t len)
+void gprs_rlcmac_dl_tbf::reuse_tbf(const uint8_t *data, const uint16_t len)
{
bts->tbf_reused();
m_llc.put_frame(data, len);
bts->llc_frame_sched();
/* reset rlc states */
- memset(&dir.dl, 0, sizeof(dir.dl));
- dir.dl.window.m_v_b.reset();
+ m_tx_counter = 0;
+ m_wait_confirm = 0;
+ m_window.reset();
/* keep to flags */
state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
@@ -1801,9 +1809,9 @@ void gprs_rlcmac_tbf::reuse_tbf(const uint8_t *data, const uint16_t len)
bts->trigger_dl_ass(this, this, NULL);
}
-bool gprs_rlcmac_tbf::dl_window_stalled() const
+bool gprs_rlcmac_dl_tbf::dl_window_stalled() const
{
- return dir.dl.window.window_stalled();
+ return m_window.window_stalled();
}
void gprs_rlcmac_tbf::rotate_in_list()
diff --git a/src/tbf.h b/src/tbf.h
index 95355bd6..23f8a7b7 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -121,21 +121,10 @@ struct gprs_rlcmac_tbf {
/* TODO: extract LLC class? */
int assemble_forward_llc(const gprs_rlc_data *data);
- struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts);
struct msgb *create_dl_ass(uint32_t fn);
struct msgb *create_ul_ass(uint32_t fn);
- struct msgb *create_ul_ack(uint32_t fn);
- int rcvd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb);
int snd_ul_ud();
- /* blocks were acked */
- int rcv_data_block_acknowledged(const uint8_t *data, size_t len, int8_t rssi);
-
- /* dispatch Unitdata.DL messages */
- static int handle(struct gprs_rlcmac_bts *bts,
- const uint32_t tlli, const char *imsi, const uint8_t ms_class,
- const uint16_t delay_csec, const uint8_t *data, const uint16_t len);
-
uint8_t tsc() const;
int rlcmac_diag();
@@ -158,8 +147,6 @@ struct gprs_rlcmac_tbf {
const char *imsi() const;
void assign_imsi(const char *imsi);
- uint16_t sns() const;
-
time_t created_ts() const;
/* attempt to make things a bit more fair */
@@ -186,27 +173,6 @@ struct gprs_rlcmac_tbf {
enum gprs_rlcmac_tbf_poll_state poll_state;
uint32_t poll_fn; /* frame number to poll */
- /* Please note that all variables here will be reset when changing
- * from WAIT RELEASE back to FLOW state (re-use of TBF).
- * All states that need reset must be in this struct, so this is why
- * variables are in both (dl and ul) structs and not outside union.
- */
- union {
- struct {
- gprs_rlc_dl_window window;
- int32_t tx_counter; /* count all transmitted blocks */
- uint8_t wait_confirm; /* wait for CCCH IMM.ASS cnf */
- } dl;
- struct {
- gprs_rlc_ul_window window;
- int32_t rx_counter; /* count all received blocks */
- uint8_t n3103; /* N3103 counter */
- uint8_t usf[8]; /* list USFs per PDCH (timeslot) */
- uint8_t contention_resolution_done; /* set after done */
- uint8_t final_ack_sent; /* set if we sent final ack */
- } ul;
- } dir;
-
gprs_rlc m_rlc;
uint8_t n3105; /* N3105 counter */
@@ -262,22 +228,10 @@ struct gprs_rlcmac_tbf {
char m_imsi[16];
protected:
- int update_window(const uint8_t ssn, const uint8_t *rbb);
- int maybe_start_new_window();
- void reuse_tbf(const uint8_t *data, const uint16_t len);
gprs_rlcmac_bts *bts_data() const;
- bool dl_window_stalled() const;
int extract_tlli(const uint8_t *data, const size_t len);
- void maybe_schedule_uplink_acknack(const rlc_ul_header *rh);
-
- int append_data(const uint8_t ms_class,
- const uint16_t pdu_delay_csec,
- const uint8_t *data, const uint16_t len);
- struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
- const int index, const bool fin_first_ack);
- struct msgb *create_new_bsn(const uint32_t fn, const uint8_t ts);
};
@@ -340,12 +294,6 @@ inline const char *gprs_rlcmac_tbf::imsi() const
return m_imsi;
}
-inline uint16_t gprs_rlcmac_tbf::sns() const
-{
- /* assume dl/ul do the same thing */
- return dir.dl.window.sns();
-}
-
const char *tbf_name(gprs_rlcmac_tbf *tbf);
inline time_t gprs_rlcmac_tbf::created_ts() const
@@ -354,9 +302,57 @@ inline time_t gprs_rlcmac_tbf::created_ts() const
}
struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
+ /* dispatch Unitdata.DL messages */
+ static int handle(struct gprs_rlcmac_bts *bts,
+ const uint32_t tlli, const char *imsi, const uint8_t ms_class,
+ const uint16_t delay_csec, const uint8_t *data, const uint16_t len);
+
+ int append_data(const uint8_t ms_class,
+ const uint16_t pdu_delay_csec,
+ const uint8_t *data, const uint16_t len);
+
+ int rcvd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb);
+ struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts);
+
+ /* Please note that all variables here will be reset when changing
+ * from WAIT RELEASE back to FLOW state (re-use of TBF).
+ * All states that need reset must be in this struct, so this is why
+ * variables are in both (dl and ul) structs and not outside union.
+ */
+ gprs_rlc_dl_window m_window;
+ int32_t m_tx_counter; /* count all transmitted blocks */
+ uint8_t m_wait_confirm; /* wait for CCCH IMM.ASS cnf */
+
+protected:
+ struct msgb *create_new_bsn(const uint32_t fn, const uint8_t ts);
+ struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
+ const int index, const bool fin_first_ack);
+ int update_window(const uint8_t ssn, const uint8_t *rbb);
+ int maybe_start_new_window();
+ bool dl_window_stalled() const;
+ void reuse_tbf(const uint8_t *data, const uint16_t len);
};
struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf {
+ struct msgb *create_ul_ack(uint32_t fn);
+
+ /* blocks were acked */
+ int rcv_data_block_acknowledged(const uint8_t *data, size_t len, int8_t rssi);
+
+ /* Please note that all variables here will be reset when changing
+ * from WAIT RELEASE back to FLOW state (re-use of TBF).
+ * All states that need reset must be in this struct, so this is why
+ * variables are in both (dl and ul) structs and not outside union.
+ */
+ gprs_rlc_ul_window m_window;
+ int32_t m_rx_counter; /* count all received blocks */
+ uint8_t m_n3103; /* N3103 counter */
+ uint8_t m_usf[8]; /* list USFs per PDCH (timeslot) */
+ uint8_t m_contention_resolution_done; /* set after done */
+ uint8_t m_final_ack_sent; /* set if we sent final ack */
+
+protected:
+ void maybe_schedule_uplink_acknack(const rlc_ul_header *rh);
};
#endif
diff --git a/tests/alloc/AllocTest.cpp b/tests/alloc/AllocTest.cpp
index 830ca900..d711ad89 100644
--- a/tests/alloc/AllocTest.cpp
+++ b/tests/alloc/AllocTest.cpp
@@ -174,7 +174,8 @@ static void test_alloc_b(int ms_class)
int tfi;
uint8_t ts_no, trx_no;
- gprs_rlcmac_tbf *ul_tbf, *dl_tbf;
+ gprs_rlcmac_ul_tbf *ul_tbf;
+ gprs_rlcmac_dl_tbf *dl_tbf;
printf("Testing DL then UL assignment followed by update\n");
@@ -199,7 +200,7 @@ static void test_alloc_b(int ms_class)
ul_tbf = tbf_alloc_ul_tbf(bts, dl_tbf, tfi, trx_no, ms_class, 0);
ul_tbf->m_tlli = 0x23;
ul_tbf->m_tlli_valid = true;
- ul_tbf->dir.ul.contention_resolution_done = 1;
+ ul_tbf->m_contention_resolution_done = 1;
OSMO_ASSERT(ul_tbf);
dump_assignment(ul_tbf, "UL");
@@ -327,7 +328,8 @@ static void test_alloc_b(bool ts0, bool ts1, bool ts2, bool ts3, bool ts4, bool
int tfi;
uint8_t ts_no, trx_no;
- gprs_rlcmac_tbf *ul_tbf, *dl_tbf;
+ gprs_rlcmac_ul_tbf *ul_tbf;
+ gprs_rlcmac_dl_tbf *dl_tbf;
bts = the_bts.bts_data();
bts->alloc_algorithm = alloc_algorithm_b;
@@ -355,7 +357,7 @@ static void test_alloc_b(bool ts0, bool ts1, bool ts2, bool ts3, bool ts4, bool
OSMO_ASSERT(ul_tbf);
ul_tbf->m_tlli = 0x23;
ul_tbf->m_tlli_valid = true;
- ul_tbf->dir.ul.contention_resolution_done = 1;
+ ul_tbf->m_contention_resolution_done = 1;
OSMO_ASSERT(dl_tbf->first_common_ts == ul_tbf->first_common_ts);