diff options
-rw-r--r-- | src/bts.cpp | 25 | ||||
-rw-r--r-- | src/encoding.cpp | 112 | ||||
-rw-r--r-- | src/encoding.h | 4 | ||||
-rw-r--r-- | src/gprs_rlcmac_sched.cpp | 56 | ||||
-rw-r--r-- | src/tbf.cpp | 208 | ||||
-rw-r--r-- | src/tbf.h | 22 | ||||
-rw-r--r-- | src/tbf_dl.cpp | 84 |
7 files changed, 222 insertions, 289 deletions
diff --git a/src/bts.cpp b/src/bts.cpp index 277726d6..d2e30320 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 06ba3376..cae783a7 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 7d807f58..4bff6155 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 4c6219ea..59e3d9d9 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 52077730..716abc1e 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; @@ -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 7540d1b3..d453137e 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; +} |