aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax <msuraev@sysmocom.de>2016-02-16 16:16:56 +0100
committerMax <msuraev@sysmocom.de>2016-02-16 16:16:56 +0100
commit33644f0f74368baddc440c378b240bb047e0534d (patch)
tree1174e369e9b6737c9b9b74c0fc2b90815959db70
parenta620359d381fa318531bd4f5d6f74890fd384269 (diff)
Add current state of Packet Timeslot Reconfiguremax/ptsr
The way it's used now (upgrade to multislot for DL TBF upon LLC frame arrival) doesn't seem right because DL and UL TBF do not exist at that moment. Nevertheless, encoding routine is complete for EGPRS (no GPRS yet) and trigger functions and state changes provide nice illustration into internal workings of the scheduler. Hence we'll keep it here for the time being. Signed-off-by: Max <msuraev@sysmocom.de>
-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;
+}