aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bts.cpp25
-rw-r--r--src/encoding.cpp112
-rw-r--r--src/encoding.h4
-rw-r--r--src/gprs_rlcmac_sched.cpp56
-rw-r--r--src/tbf.cpp208
-rw-r--r--src/tbf.h22
-rw-r--r--src/tbf_dl.cpp84
7 files changed, 222 insertions, 289 deletions
diff --git a/src/bts.cpp b/src/bts.cpp
index 277726d..d2e3032 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -555,26 +555,6 @@ int BTS::rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta)
return 0;
}
-void BTS::trigger_dl_ts_recon(gprs_rlcmac_dl_tbf *dl_tbf)//FIXME: no actual sending, just schedule trigger via state change
-{
- /* stop pending timer */
- dl_tbf->stop_timer();
-
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: Send TS RECONFIGURE for %s on PCH (IMSI=%s)\n", tbf_name(dl_tbf), dl_tbf->imsi());
-
- // FIXME: change state - dl_ass_state vs tbf->state vs state_flags
- /* change state */
- dl_tbf->set_state(GPRS_RLCMAC_RECONFIGURING); // FIXME - more flags?
- if (!(dl_tbf->state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) // FIXME: are we doing it right here?
- dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
-
- dl_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS; // FIXME: use dedicated state and enum
- dl_tbf->was_releasing = dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE); // what's was_releasing for?
-
- /* "send" PACKET TS RECON. */
- tbf_timer_start(dl_tbf, 0, Tassign_pacch); // FIXME - do we have to time this?
-}
-
/* depending on the current TBF, we assign on PACCH or AGCH */
void BTS::trigger_dl_ass(
struct gprs_rlcmac_dl_tbf *dl_tbf,
@@ -597,9 +577,6 @@ void BTS::trigger_dl_ass(
dl_tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
/* start timer */
tbf_timer_start(dl_tbf, 0, Tassign_pacch);
-
- // actual assignment creation happens in the scheduler code
-
} else {
LOGP(DRLCMAC, LOGL_DEBUG, "Send dowlink assignment for %s on PCH, no TBF exist (IMSI=%s)\n", tbf_name(dl_tbf), dl_tbf->imsi());
dl_tbf->was_releasing = dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE);
@@ -1418,7 +1395,7 @@ int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint32_t fn,
bitvec_free(block);
break;
case GPRS_RLCMAC_CONTROL_BLOCK_OPT:
- LOGP(DRLCMAC, LOGL_NOTICE, "GPRS_RLCMAC_CONTROL_BLOCK_OPT block payload is not supported.\n");
+ LOGP(DRLCMAC, LOGL_NOTICE, "GPRS_RLCMAC_CONTROL_BLOCK_OPT on FN %d with payload %s is not supported.\n", fn, osmo_hexdump((const unsigned char *)payload, len));
break;
default:
LOGP(DRLCMAC, LOGL_NOTICE, "Unknown RLCMAC block payload(%u).\n", payload);
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 06ba337..cae783a 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -439,38 +439,77 @@ CSN_DESCR_BEGIN(TRDynamic_Allocation_t)
M_TYPE_ARRAY (TRDynamic_Allocation_t, u.Timeslot_Allocation, Timeslot_Allocation_t, 8),
M_TYPE (TRDynamic_Allocation_t, u.Timeslot_Allocation_Power_Ctrl_Param, Timeslot_Allocation_Power_Ctrl_Param_t),
CSN_DESCR_END (TRDynamic_Allocation_t)
+
+CSN_DESCR_BEGIN(Timeslot_Allocation_Power_Ctrl_Param_t)
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, ALPHA, 4),
+
+ M_NEXT_EXIST (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[0].Exist, 2),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[0].USF_TN, 3),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[0].GAMMA_TN, 5),
+
+ M_NEXT_EXIST (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[1].Exist, 2),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[1].USF_TN, 3),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[1].GAMMA_TN, 5),
+
+ M_NEXT_EXIST (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[2].Exist, 2),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[2].USF_TN, 3),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[2].GAMMA_TN, 5),
+
+ M_NEXT_EXIST (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[3].Exist, 2),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[3].USF_TN, 3),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[3].GAMMA_TN, 5),
+
+ M_NEXT_EXIST (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[4].Exist, 2),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[4].USF_TN, 3),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[4].GAMMA_TN, 5),
+
+ M_NEXT_EXIST (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[5].Exist, 2),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[5].USF_TN, 3),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[5].GAMMA_TN, 5),
+
+ M_NEXT_EXIST (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[6].Exist, 2),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[6].USF_TN, 3),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[6].GAMMA_TN, 5),
+
+ M_NEXT_EXIST (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[7].Exist, 2),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[7].USF_TN, 3),
+ M_UINT (Timeslot_Allocation_Power_Ctrl_Param_t, Slot[7].GAMMA_TN, 5),
+CSN_DESCR_END (Timeslot_Allocation_Power_Ctrl_Param_t)
+
+
+CSN_DESCR_BEGIN(Timeslot_Allocation_t)
+ M_NEXT_EXIST (Timeslot_Allocation_t, Exist, 1),
+ M_UINT (Timeslot_Allocation_t, USF_TN, 3),
+CSN_DESCR_END (Timeslot_Allocation_t)
*/
/*
* PACKET TIMESLOT RECONFIGURE, sent on PACCH
* see TS 04 60, 11.2.31 and Table 9.1.9.2.1 (for WS coding)
*/
void Encoding::write_packet_ts_reconfigure(RlcMacDownlink_t * block,
- struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t rrbp,
- uint8_t alpha, uint8_t gamma, bool use_egprs)
+ struct gprs_rlcmac_dl_tbf *tbf, uint8_t poll, uint8_t rrbp,
+ uint8_t alpha, uint8_t gamma, bool use_egprs, bool use_power_ctrl)
{
block->PAYLOAD_TYPE = 1; // RLC/MAC control block that does not include the optional octets of the RLC/MAC control header
block->RRBP = rrbp; // 0: N + 13
- block->SP = poll;// RRBP field is valid
+ block->SP = poll;// RRBP field is valid?
block->USF = 0; // Uplink state flag
- block->u.Packet_Timeslot_Reconfigure.MESSAGE_TYPE = 6; // PTR
- block->u.Packet_Timeslot_Reconfigure.PAGE_MODE = 2;
+ block->u.Packet_Timeslot_Reconfigure.MESSAGE_TYPE = 7; // PTR
+ block->u.Packet_Timeslot_Reconfigure.PAGE_MODE = 3; // same as before
- if (GPRS_RLCMAC_UL_TBF == tbf->direction) {
- block->u.Packet_Timeslot_Reconfigure.Global_TFI.u.UPLINK_TFI = tbf->tfi();
- }
- else {
- block->u.Packet_Timeslot_Reconfigure.Global_TFI.u.DOWNLINK_TFI = tbf->tfi();
- }
+ block->u.Packet_Timeslot_Reconfigure.Global_TFI.u.DOWNLINK_TFI = tbf->tfi();
if (use_egprs) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: EDGE for TFI %d\n", tbf->tfi());
+ block->u.Packet_Timeslot_Reconfigure.UnionType = 1; // EGPRS
PTR_EGPRS_t *e;
e = &block->u.Packet_Timeslot_Reconfigure.u.PTR_EGPRS_Struct;
PTR_EGPRS_00_t *e00 = &e->u.PTR_EGPRS_00; // 01-11 variants are not implemented in CSN
e00->Exist_COMPACT_ReducedMA = 0; // no compact reducedMA
e00->EGPRS_ChannelCodingCommand = tbf->current_cs().to_num() - 1; // coding scheme
e00->RESEGMENT = 0; // no resegment
- e00->Exist_DOWNLINK_EGPRS_WindowSize = 0;
+ e00->Exist_DOWNLINK_EGPRS_WindowSize = 0; // FIXME: configure window size at the same time?
e00->Exist_UPLINK_EGPRS_WindowSize = 0;
e00->LINK_QUALITY_MEASUREMENT_MODE = 0; /* no meas, see TS 44.060, table 11.2.7.2 */
@@ -485,13 +524,14 @@ void Encoding::write_packet_ts_reconfigure(RlcMacDownlink_t * block,
e00->Common_Timeslot_Reconfigure_Data.CONTROL_ACK = 0; // not a new TBF
e00->Common_Timeslot_Reconfigure_Data.Exist_DOWNLINK_TFI_ASSIGNMENT = 0; // no DL. TFI ASS.
e00->Common_Timeslot_Reconfigure_Data.Exist_UPLINK_TFI_ASSIGNMENT = 0; // no UL. TFI ASS.
+
e00->Common_Timeslot_Reconfigure_Data.DOWNLINK_TIMESLOT_ALLOCATION = 0;
uint8_t tn;
for (tn = 0; tn < 8; tn++) { // FIXME: factor into separate function for both reconf. and dl_ass packets
if (tbf->pdch[tn])
- block->u.Packet_Downlink_Assignment.TIMESLOT_ALLOCATION |= 0x80 >> tn; // timeslot(s)
+ e00->Common_Timeslot_Reconfigure_Data.DOWNLINK_TIMESLOT_ALLOCATION |= 0x80 >> tn;
}
-
+ printf("PTSR TBF_TSA=%d\n", e00->Common_Timeslot_Reconfigure_Data.DOWNLINK_TIMESLOT_ALLOCATION);
e00->Common_Timeslot_Reconfigure_Data.Exist_Frequency_Parameters = 0; // no Freq. Param.
TRDynamic_Allocation_t *da = &e00->u.Dynamic_Allocation; // fixed alloc. not supported in CSN
@@ -500,24 +540,44 @@ void Encoding::write_packet_ts_reconfigure(RlcMacDownlink_t * block,
da->USF_GRANULARITY = 0; // 1 RLC/MAC block instead of 4 consecutive
da->Exist_RLC_DATA_BLOCKS_GRANTED = 0;
da->Exist_TBF_Starting_Time = 0;
- Timeslot_Allocation_Power_Ctrl_Param_t *pp = &da->u.Timeslot_Allocation_Power_Ctrl_Param;
- pp->ALPHA = alpha;
- for (tn = 0; tn < 8; tn++) // FIXME: factor into separate function for both reconf. and dl_ass packets
- {
- if (tbf->pdch[tn]) {
- pp->Slot[tn].Exist = 1; // Slot[i] = on
- pp->Slot[tn].USF_TN = tbf->pdch[tn]->assigned_usf(); // tbf->m_usf[tn] - for uplink only
- pp->Slot[tn].GAMMA_TN = gamma; // GAMMA_TN
- }
- else {
- pp->Slot[tn].Exist = 0; // Slot[i] = off
- }
+
+ if (use_power_ctrl) {
+ Timeslot_Allocation_Power_Ctrl_Param_t *pp = &da->u.Timeslot_Allocation_Power_Ctrl_Param;
+ pp->ALPHA = alpha;
+ for (tn = 0; tn < 8; tn++) // FIXME: factor into separate function for both reconf. and dl_ass packets
+ {
+ printf("tbf... %d\n", tbf->pdch[tn]);
+ if (tbf->pdch[tn]) {
+ pp->Slot[tn].Exist = 1; // Slot[i] = on
+ pp->Slot[tn].USF_TN = tbf->pdch[tn]->assigned_usf(); // tbf->m_usf[tn] - for uplink only
+ pp->Slot[tn].GAMMA_TN = gamma; // GAMMA_TN
+ }
+ else {
+ pp->Slot[tn].Exist = 0; // Slot[i] = off
+ }
+ }
+ } else {
+
+ for (tn = 0; tn < 8; tn++) // FIXME: factor into separate function for both reconf. and dl_ass packets
+ {
+ if (tbf->pdch[tn]) {
+ (&da->u.Timeslot_Allocation[tn])->Exist = 1;
+ (&da->u.Timeslot_Allocation[tn])->USF_TN = tbf->pdch[tn]->assigned_usf();//tbf->m_usf[ts] equivalent for DL?
+ //(&da->u.Timeslot_Allocation[tn])->USF_TN = tbf->m_usf[tn];
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: TN %d assigned USF %d\n", tn, (&da->u.Timeslot_Allocation[tn])->USF_TN);
+ } else {
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: TN %d not used\n", tn);
+ (&da->u.Timeslot_Allocation[tn])->Exist = 0;
+ }
+ }
}
} else {
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: GPRS for TFI %d\n", tbf->tfi());
PTR_GPRS_t *g;
g = &block->u.Packet_Timeslot_Reconfigure.u.PTR_GPRS_Struct;
}
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: encoding complete\n");
}
/*
CSN_DESCR_BEGIN (Packet_Downlink_Assignment_t)
diff --git a/src/encoding.h b/src/encoding.h
index 7d807f5..4bff615 100644
--- a/src/encoding.h
+++ b/src/encoding.h
@@ -61,8 +61,8 @@ public:
int8_t ta_idx, uint8_t ta_ts, bool use_egprs);
static void write_packet_ts_reconfigure(RlcMacDownlink_t * block,
- struct gprs_rlcmac_tbf *tbf, uint8_t poll, uint8_t rrbp,
- uint8_t alpha, uint8_t gamma, bool use_egprs);
+ struct gprs_rlcmac_dl_tbf *tbf, uint8_t poll, uint8_t rrbp,
+ uint8_t alpha, uint8_t gamma, bool use_egprs, bool use_power_ctrl);
static void encode_rbb(const char *show_rbb, uint8_t *rbb);
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp
index 4c6219e..59e3d9d 100644
--- a/src/gprs_rlcmac_sched.cpp
+++ b/src/gprs_rlcmac_sched.cpp
@@ -25,12 +25,14 @@
#include "pcu_utils.h"
+#warning pass the parameters by struct???
static uint32_t sched_poll(BTS *bts,
uint8_t trx, uint8_t ts, uint32_t fn, uint8_t block_nr,
struct gprs_rlcmac_tbf **poll_tbf,
struct gprs_rlcmac_tbf **ul_ass_tbf,
struct gprs_rlcmac_tbf **dl_ass_tbf,
- struct gprs_rlcmac_ul_tbf **ul_ack_tbf)
+ struct gprs_rlcmac_ul_tbf **ul_ack_tbf,
+ struct gprs_rlcmac_dl_tbf **dl_recon_tbf)
{
struct gprs_rlcmac_ul_tbf *ul_tbf;
struct gprs_rlcmac_dl_tbf *dl_tbf;
@@ -47,7 +49,7 @@ static uint32_t sched_poll(BTS *bts,
OSMO_ASSERT(ul_tbf);
/* this trx, this ts */
if (ul_tbf->trx->trx_no != trx || !ul_tbf->is_control_ts(ts))
- continue;
+ continue;
/* polling for next uplink block */
if (ul_tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
&& ul_tbf->poll_fn == poll_fn)
@@ -66,10 +68,6 @@ static uint32_t sched_poll(BTS *bts,
/* this trx, this ts */
if (dl_tbf->trx->trx_no != trx || !dl_tbf->is_control_ts(ts))
continue;
-
-// FIXME: add _state and scheduling here for PTSR
-
-
/* polling for next uplink block */
if (dl_tbf->poll_state == GPRS_RLCMAC_POLL_SCHED
&& dl_tbf->poll_fn == poll_fn)
@@ -78,6 +76,10 @@ static uint32_t sched_poll(BTS *bts,
*dl_ass_tbf = dl_tbf;
if (dl_tbf->ul_ass_state == GPRS_RLCMAC_UL_ASS_SEND_ASS)
*ul_ass_tbf = dl_tbf;
+ if (dl_tbf->needs_recon_to_be_scheduled()) {
+ *dl_recon_tbf = dl_tbf;
+ printf("PTSR! %s:%d\n", __func__, __LINE__);
+ }
}
return poll_fn;
@@ -123,30 +125,18 @@ 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_ul_tbf *ul_ack_tbf) // FIXME: add one more parameter and corresponding logic for PTSR
+ struct gprs_rlcmac_ul_tbf *ul_ack_tbf,
+ struct gprs_rlcmac_dl_tbf *dl_recon_tbf)
{
struct msgb *msg = NULL;
struct gprs_rlcmac_tbf *tbf = NULL;
- struct gprs_rlcmac_tbf *next_list[3] = { ul_ass_tbf, dl_ass_tbf, ul_ack_tbf };
+ struct gprs_rlcmac_tbf *next_list[] = { ul_ass_tbf, dl_ass_tbf, ul_ack_tbf, dl_recon_tbf };
for (size_t i = 0; i < ARRAY_SIZE(next_list); ++i) {
- tbf = next_list[(pdch->next_ctrl_prio + i) % 3];
+ tbf = next_list[(pdch->next_ctrl_prio + i) % 4];
if (!tbf)
continue;
- // schedule PTSR if necessary
- if (tbf->direction == GPRS_RLCMAC_DL_TBF && tbf->state_is(GPRS_RLCMAC_RECONFIGURING)) {
- //tbf = dl_ass_tbf;
- //msg = tbf->create_dl_ts_recon(fn, ts);
- if (tbf == dl_ass_tbf) {
- LOGP(DRLCMACSCHED, LOGL_NOTICE, "PTSR: scheduling on %s\n", tbf_name(dl_ass_tbf));
- msg = dl_ass_tbf->create_dl_ts_recon(fn, ts);
- if (msg)
- break;
- } else
- LOGP(DRLCMACSCHED, LOGL_NOTICE, "PTSR: FIXME - scheduling PTSR on non-DL TBF\n");
- }
-
/*
* Assignments for the same direction have lower precedence,
* because they may kill the TBF when the CONTOL ACK is
@@ -159,17 +149,20 @@ static struct msgb *sched_select_ctrl_msg(
msg = dl_ass_tbf->create_dl_ass(fn, ts);
else if (tbf == ul_ack_tbf)
msg = ul_ack_tbf->create_ul_ack(fn, ts);
-
+ else if (tbf == dl_recon_tbf) {
+ msg = dl_recon_tbf->create_recon(fn, ts);
+ printf("PTSR! %s:%d %s\n", __func__, __LINE__, msgb_hexdump(msg));
+ }
if (!msg) {
tbf = NULL;
continue;
}
pdch->next_ctrl_prio += 1;
- pdch->next_ctrl_prio %= 3;
+ pdch->next_ctrl_prio %= 4;
break;
}
-
+
if (!msg) {
/*
* If one of these is left, the response (CONTROL ACK) from the
@@ -184,7 +177,7 @@ static struct msgb *sched_select_ctrl_msg(
msg = ul_ass_tbf->create_ul_ass(fn, ts);
}
}
-
+
/* any message */
if (msg) {
tbf->rotate_in_list();
@@ -311,8 +304,9 @@ 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_ass_tbf = NULL;
struct gprs_rlcmac_ul_tbf *ul_ack_tbf = NULL;
+ struct gprs_rlcmac_dl_tbf *dl_recon_tbf = NULL;
uint8_t usf = 0x7;
struct msgb *msg = NULL;
uint32_t poll_fn, sba_fn;
@@ -333,14 +327,16 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
pdch->last_rts_fn = fn;
poll_fn = sched_poll(bts->bts, trx, ts, fn, block_nr, &poll_tbf, &ul_ass_tbf,
- &dl_ass_tbf, &ul_ack_tbf);
+ &dl_ass_tbf, &ul_ack_tbf, &dl_recon_tbf);
/* check uplink resource for polling */
- if (poll_tbf)
+ if (poll_tbf){
+ printf("TBF=%s, FN=%d, POLL_FN=%d\n", tbf_name(poll_tbf), fn, poll_fn);
LOGP(DRLCMACSCHED, LOGL_DEBUG, "Received RTS for PDCH: TRX=%d "
"TS=%d FN=%d block_nr=%d scheduling free USF for "
"polling at FN=%d of %s\n", trx, ts, fn,
block_nr, poll_fn,
tbf_name(poll_tbf));
+ }
/* use free USF */
/* else. check for sba */
else if ((sba_fn = bts->bts->sba()->sched(trx, ts, fn, block_nr) != 0xffffffff))
@@ -355,7 +351,7 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts,
/* Prio 1: select control message */
msg = sched_select_ctrl_msg(trx, ts, fn, block_nr, pdch, ul_ass_tbf,
- dl_ass_tbf, ul_ack_tbf);
+ dl_ass_tbf, ul_ack_tbf, dl_recon_tbf);
/* Prio 2: select data message for downlink */
if (!msg)
diff --git a/src/tbf.cpp b/src/tbf.cpp
index 5207773..716abc1 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -399,6 +399,7 @@ const char *gprs_rlcmac_tbf::tbf_state_name[] = {
"FINISHED",
"WAIT RELEASE",
"RELEASING",
+ "RECONFIGURING",
};
void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int T,
@@ -854,19 +855,14 @@ void gprs_rlcmac_tbf::handle_timeout()
/* This tbf can be upgraded to use multiple DL
* timeslots and now that there is already one
* slot assigned send another DL assignment via
- * PDCH. */
+ * PDCH.
+ * We have decided it is worthwhile to upgrade this
+ * TBF to multislot and we do it by scheduling the
+ * TS Downlink reconfigure message
+ */
/* keep to flags */
- dl_tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
-
- dl_tbf->update(); // do the MSLOT assignment
-
-// dl_tbf->bts->trigger_dl_ass(dl_tbf, dl_tbf); // FIXME: use write_packet_ts_reconfigure()
- //LOGP(DRLCMAC, LOGL_NOTICE, "DL. ASS. for multislot\n");
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: trigger for multislot\n");
- dl_tbf->bts->trigger_dl_ts_recon(dl_tbf);
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: trigger set\n");
-// abort(); // CRASH!
+ dl_tbf->reconfigure_for_multislot();
} else
LOGP(DRLCMAC, LOGL_NOTICE, "%s Continue flow after "
"IMM.ASS confirm\n", tbf_name(dl_tbf));
@@ -910,196 +906,6 @@ int gprs_rlcmac_tbf::rlcmac_diag()
return 0;
}
-struct msgb *gprs_rlcmac_tbf::create_dl_ts_recon_exp(uint32_t fn, uint8_t ts)
-{
- // FIXME - check appropriate flags?
-
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: GPRS_RLCMAC_RECONFIGURING: preparing msg\n");
- unsigned int rrbp = 0;
- uint32_t new_poll_fn = 0;
- struct msgb *msg;
-
- int rc = this->check_polling(fn, ts, &new_poll_fn, &rrbp);
- if (rc < 0) {
- LOGP(DRLCMAC, LOGL_ERROR, "PTSR: check polling failed!\n");
- return NULL;
- }
-// LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: polling checked\n");
- msg = msgb_alloc(23, "rlcmac_pack_ts_recon");
- if (!msg) {
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: msg alloc failed\n");
- return NULL;
- }
-// LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: msg alloc ok\n");
- bitvec *recon_vec = bitvec_alloc(123);
- if (!recon_vec) {
- msgb_free(msg);
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: bitvec alloc failed\n");
- return NULL;
- }
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: bitvec alloc ok\n");
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: %s start Packet TS Reconfigure (PACCH)\n", tbf_name(this)); // abort()?
- bitvec_unhex(recon_vec, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
- RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
-
- Encoding::write_packet_ts_reconfigure(mac_control_block, this, new_poll_fn, rrbp, bts_data()->alpha, bts_data()->gamma, this->is_egprs_enabled());
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: +++++++++++++++++++++++++ TX : Packet TS Reconfigure +++++++++++++++++++++++++\n");
- encode_gsm_rlcmac_downlink(recon_vec, mac_control_block);
- LOGPC(DCSN1, LOGL_NOTICE, "\n");
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: _________________________ TX : Packet TS Reconfigure _________________________\n");
-
- bitvec_pack(recon_vec, msgb_put(msg, 23)); // FIXME - size?
- bitvec_free(recon_vec);
- talloc_free(mac_control_block);
-
-// FIXME: change to proper state before returning
-// if (poll_ass_dl) {
- set_polling(new_poll_fn, ts);
- // if (new_dl_tbf->state_is(GPRS_RLCMAC_ASSIGN))
- this->set_state(GPRS_RLCMAC_WAIT_ASSIGN);
- dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK;
- LOGP(DRLCMACDL, LOGL_INFO,
- "%s Scheduled PTSR polling on FN=%d, TS=%d\n",
- name(), poll_fn, poll_ts);
-/* } else {
- dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
- new_dl_tbf->set_state(GPRS_RLCMAC_FLOW);
- tbf_assign_control_ts(new_dl_tbf);
- // stop pending assignment timer
- new_dl_tbf->stop_timer();
- }
-*/
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: msg assembled ok\n");
- return msg;
-}
-
-struct msgb *gprs_rlcmac_tbf::create_dl_ts_recon(uint32_t fn, uint8_t ts)
-{
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: GPRS_RLCMAC_RECONFIGURING: preparing msg\n");
- struct msgb *msg;
- struct gprs_rlcmac_dl_tbf *new_dl_tbf = NULL;
- int poll_ass_dl = 1;
- unsigned int rrbp = 0;
- uint32_t new_poll_fn = 0;
- int rc;
- bool old_tfi_is_valid = is_tfi_assigned();
-
- if (direction == GPRS_RLCMAC_DL_TBF && !is_control_ts(ts)) {
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: Cannot poll for downlink "
- "assigment, because MS cannot reply. (TS=%d, "
- "first common TS=%d)\n", ts,
- first_common_ts);
- poll_ass_dl = 0;
- }
- if (poll_ass_dl) {
- if (poll_state == GPRS_RLCMAC_POLL_SCHED &&
- ul_ass_state == GPRS_RLCMAC_UL_ASS_WAIT_ACK)
- {
- LOGP(DRLCMACUL, LOGL_DEBUG, "PTSR: Polling is already "
- "scheduled for %s, so we must wait for the uplink "
- "assignment...\n", tbf_name(this));
- return NULL;
- }
- rc = check_polling(fn, ts, &new_poll_fn, &rrbp);
- if (rc < 0) {
- LOGP(DRLCMAC, LOGL_ERROR, "PTSR: check polling failed!\n");
- return NULL;
- }
- }
-
- /* on uplink TBF we get the downlink TBF to be assigned. */
- if (direction == GPRS_RLCMAC_UL_TBF) {
- gprs_rlcmac_ul_tbf *ul_tbf = as_ul_tbf(this);
-
- /* be sure to check first, if contention resolution is done,
- * otherwise we cannot send the assignment yet */
- if (!ul_tbf->m_contention_resolution_done) {
- LOGP(DRLCMAC, LOGL_DEBUG, "PTSR: Cannot assign DL TBF now, "
- "because contention resolution is not "
- "finished.\n");
- return NULL;
- }
- }
-
- if (ms())
- new_dl_tbf = ms()->dl_tbf();
-
- if (!new_dl_tbf) {
- LOGP(DRLCMACDL, LOGL_ERROR, "PTSR: We have a schedule for downlink "
- "assignment at %s, but there is no downlink "
- "TBF\n", tbf_name(this));
- dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
- return NULL;
- }
-
- if (new_dl_tbf == as_dl_tbf(this))
- LOGP(DRLCMAC, LOGL_DEBUG,
- "PTSR: New and old TBF are the same %s\n", name());
-
- if (old_tfi_is_valid && !new_dl_tbf->is_tlli_valid()) {
- LOGP(DRLCMACDL, LOGL_ERROR,
- "PTSR: The old TFI is not assigned and there is no "
- "TLLI. Old TBF %s, new TBF %s\n",
- name(), new_dl_tbf->name());
- dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
- return NULL;
- }
-
- new_dl_tbf->was_releasing = was_releasing;
- msg = msgb_alloc(23, "rlcmac_dl_ts_rec");
- if (!msg)
- return NULL;
- bitvec *ass_vec = bitvec_alloc(23);
- if (!ass_vec) {
- msgb_free(msg);
- return NULL;
- }
- bitvec_unhex(ass_vec,
- "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
- LOGP(DRLCMAC, LOGL_INFO, "PTSR: %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,
- old_tfi_is_valid, m_tfi, (direction == GPRS_RLCMAC_DL_TBF),
- new_dl_tbf, poll_ass_dl, rrbp,
- bts_data()->alpha, bts_data()->gamma, -1, 0,
- is_egprs_enabled());
- LOGP(DRLCMAC, LOGL_DEBUG, "+++++++++++++++++++++++++ TX : Packet Downlink Assignment +++++++++++++++++++++++++\n");
- encode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
- LOGPC(DCSN1, LOGL_NOTICE, "\n");
- LOGP(DRLCMAC, LOGL_DEBUG, "------------------------- TX : Packet Downlink Assignment -------------------------\n");
-*/
- Encoding::write_packet_ts_reconfigure(mac_control_block, new_dl_tbf, new_poll_fn, rrbp, bts_data()->alpha, bts_data()->gamma, is_egprs_enabled());
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: +++++++++++++++++++++++++ TX : Packet TS Reconfigure +++++++++++++++++++++++++\n");
- encode_gsm_rlcmac_downlink(ass_vec, mac_control_block);
- LOGPC(DCSN1, LOGL_NOTICE, "\n");
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: _________________________ TX : Packet TS Reconfigure _________________________\n");
- /*end diff*/
-
- bitvec_pack(ass_vec, msgb_put(msg, 23));
- bitvec_free(ass_vec);
- talloc_free(mac_control_block);
-
- if (poll_ass_dl) {
- set_polling(new_poll_fn, ts);
- if (new_dl_tbf->state_is(GPRS_RLCMAC_ASSIGN))
- new_dl_tbf->set_state(GPRS_RLCMAC_WAIT_ASSIGN);
- dl_ass_state = GPRS_RLCMAC_DL_ASS_WAIT_ACK;
- LOGP(DRLCMACDL, LOGL_INFO,
- "PTSR: %s Scheduled DL Assignment polling on FN=%d, TS=%d\n",
- name(), poll_fn, poll_ts);
- } else {
- dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE;
- new_dl_tbf->set_state(GPRS_RLCMAC_FLOW);
- tbf_assign_control_ts(new_dl_tbf);
- /* stop pending assignment timer */
- new_dl_tbf->stop_timer();
-
- }
- LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: msgb=%s\n", msgb_hexdump(msg));
- return msg;
-}
-
struct msgb *gprs_rlcmac_tbf::create_dl_ass(uint32_t fn, uint8_t ts)
{
struct msgb *msg;
diff --git a/src/tbf.h b/src/tbf.h
index 207710a..1a23e43 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -59,13 +59,13 @@ enum gprs_rlcmac_tbf_poll_state {
enum gprs_rlcmac_tbf_dl_ts_recon_state {
GPRS_RLCMAC_DL_TS_RECON_NONE = 0,
- GPRS_RLCMAC_DL_TS_RECON_SEND, /* send PTSR on next RTS */
+ GPRS_RLCMAC_DL_TS_RECON_SEND, /* send PTSR on next RTS */
GPRS_RLCMAC_DL_TS_RECON_WAIT_ACK, /* wait for PACKET CONTROL ACK */
};
enum gprs_rlcmac_tbf_dl_ass_state {
GPRS_RLCMAC_DL_ASS_NONE = 0,
- GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
+ GPRS_RLCMAC_DL_ASS_SEND_ASS, /* send downlink assignment on next RTS */
GPRS_RLCMAC_DL_ASS_WAIT_ACK, /* wait for PACKET CONTROL ACK */
};
@@ -110,9 +110,8 @@ struct gprs_rlcmac_tbf {
const char *name() const;
struct msgb *create_dl_ass(uint32_t fn, uint8_t ts);
- struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
- struct msgb *create_dl_ts_recon_exp(uint32_t fn, uint8_t ts);
- struct msgb *create_dl_ts_recon(uint32_t fn, uint8_t ts);
+ struct msgb *create_ul_ass(uint32_t fn, uint8_t ts);
+
GprsMs *ms() const;
void set_ms(GprsMs *ms);
@@ -239,7 +238,7 @@ protected:
int set_tlli_from_ul(uint32_t new_tlli);
void merge_and_clear_ms(GprsMs *old_ms);
- static const char *tbf_state_name[7];
+ static const char *tbf_state_name[8];
class GprsMs *m_ms;
@@ -380,6 +379,10 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
int release();
int abort();
+ bool needs_recon_to_be_scheduled() const;
+ void reconfigure_for_multislot();
+ msgb *create_recon(uint32_t fn, uint8_t ts);
+
/* TODO: add the gettimeofday as parameter */
struct msgb *llc_dequeue(bssgp_bvc_ctx *bctx);
@@ -407,6 +410,8 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf {
} m_bw;
protected:
+ enum gprs_rlcmac_tbf_dl_ts_recon_state m_recon_state;
+
struct ana_result {
unsigned received_packets;
unsigned lost_packets;
@@ -495,4 +500,9 @@ inline gprs_rlc_window *gprs_rlcmac_tbf::window()
return NULL;
}
+inline bool gprs_rlcmac_dl_tbf::needs_recon_to_be_scheduled() const
+{
+ return m_recon_state == GPRS_RLCMAC_DL_TS_RECON_SEND;
+}
+
#endif
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index 7540d1b..d453137 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -43,6 +43,8 @@ extern "C" {
/* After sending these frames, we poll for ack/nack. */
#define POLL_ACK_AFTER_FRAMES 20
+extern void *tall_pcu_ctx;
+
extern "C" {
int bssgp_tx_llc_discarded(struct bssgp_bvc_ctx *bctx, uint32_t tlli,
uint8_t num_frames, uint32_t num_octets);
@@ -1125,3 +1127,85 @@ bool gprs_rlcmac_dl_tbf::keep_open(unsigned fn) const
keep_time_frames = msecs_to_frames(bts_data()->dl_tbf_idle_msec);
return frames_since_last_drain(fn) <= keep_time_frames;
}
+
+void gprs_rlcmac_dl_tbf::reconfigure_for_multislot()
+{
+ printf("PTSR! %s:%d\n", __func__, __LINE__);
+ /* Clear old state */
+ state_flags &= GPRS_RLCMAC_FLAG_TO_MASK;
+
+ /* Trigger a multislot assignment by updating this tbf */
+ update();
+
+ /* Schedule this to be sent to the MS */
+ stop_timer();
+ m_recon_state = GPRS_RLCMAC_DL_TS_RECON_SEND;
+ set_state(GPRS_RLCMAC_RECONFIGURING);
+ /* ??? */
+ if (!(state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH)))
+ state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH);
+ /* TODO... start a timer */
+}
+
+msgb *gprs_rlcmac_dl_tbf::create_recon(uint32_t fn, uint8_t ts)
+{
+ msgb *msg;
+ unsigned int rrbp = 0, should_poll;
+ uint32_t new_poll_fn = 0;
+
+ // OSMO_ASSERT(needs_recon_to_be_scheduled()); // makes tests unnecessary hard
+ // printf("PTSR! %s:%d for FN=%d, TS=%d\n", __func__, __LINE__, fn, ts);
+
+ if (!is_control_ts(ts)) {
+ // LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: Cannot poll because MS cannot reply. (TS=%d, first common TS=%d)\n", ts, first_common_ts);
+ printf("PTSR: Cannot poll because MS cannot reply. (TS=%d, first common TS=%d)\n", ts, first_common_ts);
+ should_poll = 0;
+ } else {
+ // LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: we should poll on TS=%d\n", ts);
+ printf("PTSR: we should poll on TS=%d\n", ts);
+ should_poll = 1;
+ int rc = check_polling(fn, ts, &new_poll_fn, &rrbp);
+ if (rc < 0) {
+ printf("PTSR! %s:%d\n", __func__, __LINE__);
+ return NULL;
+ }
+ }
+
+ msg = msgb_alloc(23, "rlcmac_pack_ts_recon");
+ if (!msg) {
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: msg alloc failed\n");
+ return NULL;
+ }
+ bitvec *recon_vec = bitvec_alloc(23);
+ if (!recon_vec) {
+ msgb_free(msg);
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: bitvec alloc failed\n");
+ return NULL;
+ }
+
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: bitvec alloc ok\n");
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: %s start Packet TS Reconfigure (PACCH)\n", tbf_name(this));
+ bitvec_unhex(recon_vec, "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b");
+ RlcMacDownlink_t * mac_control_block = (RlcMacDownlink_t *)talloc_zero(tall_pcu_ctx, RlcMacDownlink_t);
+
+ Encoding::write_packet_ts_reconfigure(mac_control_block, this, should_poll, rrbp, bts_data()->alpha, bts_data()->gamma, this->is_egprs_enabled(), 1);
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: +++++++++++++++++++++++++ TX : Packet TS Reconfigure +++++++++++++++++++++++++\n");
+ encode_gsm_rlcmac_downlink(recon_vec, mac_control_block);
+ LOGPC(DCSN1, LOGL_NOTICE, "\n");
+ LOGP(DRLCMAC, LOGL_NOTICE, "PTSR: _________________________ TX : Packet TS Reconfigure _________________________\n");
+
+ bitvec_pack(recon_vec, msgb_put(msg, 23)); // FIXME - size?
+ bitvec_free(recon_vec);
+ talloc_free(mac_control_block);
+
+ if (should_poll) {
+ set_polling(new_poll_fn, ts);
+ }
+ // FIXME: adjust state according to polling status
+ m_recon_state = GPRS_RLCMAC_DL_TS_RECON_WAIT_ACK;
+
+ /* update the control_ts after the ack? */
+ //tbf_assign_control_ts(this); // already assigned?
+
+ return msg;
+}