diff options
Diffstat (limited to 'src/gprs_rlcmac_sched.cpp')
-rw-r--r-- | src/gprs_rlcmac_sched.cpp | 78 |
1 files changed, 32 insertions, 46 deletions
diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp index 8867d436..ac581216 100644 --- a/src/gprs_rlcmac_sched.cpp +++ b/src/gprs_rlcmac_sched.cpp @@ -11,10 +11,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include <gprs_bssgp_pcu.h> @@ -32,6 +28,7 @@ extern "C" { #include <osmocom/core/gsmtap.h> + #include "nacc_fsm.h" } struct tbf_sched_candidates { @@ -49,35 +46,27 @@ static void get_ctrl_msg_tbf_candidates(const struct gprs_rlcmac_pdch *pdch, struct llist_item *pos; llist_for_each_entry(pos, &pdch->trx->ul_tbfs, list) { - ul_tbf = as_ul_tbf((struct gprs_rlcmac_tbf *)pos->entry); + ul_tbf = tbf_as_ul_tbf((struct gprs_rlcmac_tbf *)pos->entry); OSMO_ASSERT(ul_tbf); - /* this trx, this ts */ - if (!ul_tbf->is_control_ts(pdch->ts_no)) - continue; - if (tbf_ul_ack_rts(ul_tbf)) + if (tbf_ul_ack_rts(ul_tbf, pdch)) tbf_cand->ul_ack = ul_tbf; - if (tbf_dl_ass_rts(ul_tbf)) + if (tbf_dl_ass_rts(ul_tbf, pdch)) tbf_cand->dl_ass = ul_tbf; - if (tbf_ul_ass_rts(ul_tbf)) + if (tbf_ul_ass_rts(ul_tbf, pdch)) tbf_cand->ul_ass = ul_tbf; - /* NACC ready to send. TFI assigned is needed to send messages */ - if (ul_tbf->is_tfi_assigned() && ms_nacc_rts(ul_tbf->ms())) + if (tbf_nacc_rts(ul_tbf, pdch)) tbf_cand->nacc = ul_tbf; /* FIXME: 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_for_each_entry(pos, &pdch->trx->dl_tbfs, list) { - dl_tbf = as_dl_tbf((struct gprs_rlcmac_tbf *)pos->entry); + dl_tbf = tbf_as_dl_tbf((struct gprs_rlcmac_tbf *)pos->entry); OSMO_ASSERT(dl_tbf); - /* this trx, this ts */ - if (!dl_tbf->is_control_ts(pdch->ts_no)) - continue; - if (tbf_dl_ass_rts(dl_tbf)) + if (tbf_dl_ass_rts(dl_tbf, pdch)) tbf_cand->dl_ass = dl_tbf; - if (tbf_ul_ass_rts(dl_tbf)) + if (tbf_ul_ass_rts(dl_tbf, pdch)) tbf_cand->ul_ass = dl_tbf; - /* NACC ready to send. TFI assigned is needed to send messages */ - if (dl_tbf->is_tfi_assigned() && ms_nacc_rts(dl_tbf->ms())) + if (tbf_nacc_rts(dl_tbf, pdch)) tbf_cand->nacc = dl_tbf; } } @@ -150,7 +139,6 @@ static struct msgb *sched_select_ctrl_msg(struct gprs_rlcmac_pdch *pdch, uint32_ tbfs->dl_ass, tbfs->ul_ack, tbfs->nacc }; - uint8_t ts = pdch->ts_no; /* Send Packet Application Information first (ETWS primary notifications) */ msg = sched_app_info(tbfs->dl_ass); @@ -167,16 +155,15 @@ static struct msgb *sched_select_ctrl_msg(struct gprs_rlcmac_pdch *pdch, uint32_ * received, thus preventing the others from being processed. */ if (tbf == tbfs->ul_ass && tbf->ul_ass_state_is(TBF_UL_ASS_SEND_ASS_REJ)) - msg = tbf_ul_ass_create_rlcmac_msg(tbfs->ul_ass, fn, ts); + msg = tbf_ul_ass_create_rlcmac_msg(tbfs->ul_ass, pdch, fn); else if (tbf == tbfs->ul_ass && tbf->direction == GPRS_RLCMAC_DL_TBF) - msg = tbf_ul_ass_create_rlcmac_msg(tbfs->ul_ass, fn, ts); + msg = tbf_ul_ass_create_rlcmac_msg(tbfs->ul_ass, pdch, fn); else if (tbf == tbfs->dl_ass && tbf->direction == GPRS_RLCMAC_UL_TBF) - msg = tbf_dl_ass_create_rlcmac_msg(tbfs->dl_ass, fn, ts); + msg = tbf_dl_ass_create_rlcmac_msg(tbfs->dl_ass, pdch, fn); else if (tbf == tbfs->ul_ack) - msg = tbf_ul_ack_create_rlcmac_msg(tbfs->ul_ack, fn, ts); - else if (tbf == tbfs->nacc) { - msg = ms_nacc_create_rlcmac_msg(tbf->ms(), tbf, fn, ts); - } + msg = tbf_ul_ack_create_rlcmac_msg(tbfs->ul_ack, pdch, fn); + else if (tbf == tbfs->nacc) + msg = ms_nacc_create_rlcmac_msg(tbf->ms(), tbf, pdch, fn); if (!msg) { tbf = NULL; @@ -196,10 +183,10 @@ static struct msgb *sched_select_ctrl_msg(struct gprs_rlcmac_pdch *pdch, uint32_ */ if (tbfs->dl_ass) { tbf = tbfs->dl_ass; - msg = tbf_dl_ass_create_rlcmac_msg(tbfs->dl_ass, fn, ts); + msg = tbf_dl_ass_create_rlcmac_msg(tbfs->dl_ass, pdch, fn); } else if (tbfs->ul_ass) { tbf = tbfs->ul_ass; - msg = tbf_ul_ass_create_rlcmac_msg(tbfs->ul_ass, fn, ts); + msg = tbf_ul_ass_create_rlcmac_msg(tbfs->ul_ass, pdch, fn); } } @@ -231,24 +218,25 @@ static struct msgb *sched_select_ctrl_msg(struct gprs_rlcmac_pdch *pdch, uint32_ } static inline enum tbf_dl_prio tbf_compute_priority(const struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_dl_tbf *tbf, - uint8_t ts, uint32_t fn, int age) + const struct gprs_rlcmac_pdch *pdch, uint32_t fn, int age) { const gprs_rlc_dl_window *w = static_cast<gprs_rlc_dl_window *>(tbf->window()); unsigned long msecs_t3190 = osmo_tdef_get(the_pcu->T_defs, 3190, OSMO_TDEF_MS, -1); unsigned long dl_tbf_idle_msec = osmo_tdef_get(the_pcu->T_defs, -2031, OSMO_TDEF_MS, -1); int age_thresh1 = msecs_to_frames(200); int age_thresh2 = msecs_to_frames(OSMO_MIN(msecs_t3190/2, dl_tbf_idle_msec)); + const bool is_control_ts = tbf_is_control_ts(tbf, pdch); - if (tbf->is_control_ts(ts) && tbf->need_poll_for_dl_ack_nack()) + if (is_control_ts && tbf->need_poll_for_dl_ack_nack()) return DL_PRIO_CONTROL; - if (tbf->is_control_ts(ts) && age > age_thresh2 && age_thresh2 > 0) + if (is_control_ts && age > age_thresh2 && age_thresh2 > 0) return DL_PRIO_HIGH_AGE; if ((tbf->state_is(TBF_ST_FLOW) && tbf->have_data()) || w->resend_needed() >= 0) return DL_PRIO_NEW_DATA; - if (tbf->is_control_ts(ts) && age > age_thresh1 && tbf->keep_open(fn)) + if (is_control_ts && age > age_thresh1 && tbf->keep_open(fn)) return DL_PRIO_LOW_AGE; if (!w->window_empty()) @@ -289,7 +277,6 @@ static struct msgb *sched_select_dl_data_msg(struct gprs_rlcmac_bts *bts, struct struct msgb *msg = NULL; struct gprs_rlcmac_dl_tbf *tbf, *prio_tbf = NULL; enum tbf_dl_prio prio, max_prio = DL_PRIO_NONE; - uint8_t ts = pdch->ts_no; uint8_t i, tfi, prio_tfi; int age; @@ -316,7 +303,7 @@ static struct msgb *sched_select_dl_data_msg(struct gprs_rlcmac_bts *bts, struct age = tbf->frames_since_last_poll(fn); /* compute priority */ - prio = tbf_compute_priority(bts, tbf, ts, fn, age); + prio = tbf_compute_priority(bts, tbf, pdch, fn, age); if (prio == DL_PRIO_NONE) continue; @@ -345,7 +332,7 @@ static struct msgb *sched_select_dl_data_msg(struct gprs_rlcmac_bts *bts, struct /* next TBF to handle resource is the next one */ pdch->next_dl_tfi = (prio_tfi + 1) & 31; /* generate DL data block */ - msg = prio_tbf->create_dl_acked_block(fn, ts, req_mcs_kind); + msg = prio_tbf->create_dl_acked_block(fn, pdch, req_mcs_kind); *is_egprs = prio_tbf->is_egprs_enabled(); } @@ -460,8 +447,8 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts, * let's set its USF in the DL msg. This is not really needed, * but it helps understand better the flow when looking at * pcaps. */ - if (poll_tbf->direction == GPRS_RLCMAC_UL_TBF && as_ul_tbf(poll_tbf)->m_usf[ts] != USF_INVALID) - usf_tbf = as_ul_tbf(poll_tbf); + if (poll_tbf->direction == GPRS_RLCMAC_UL_TBF && tbf_as_ul_tbf(poll_tbf)->m_usf[ts] != USF_INVALID) + usf_tbf = tbf_as_ul_tbf(poll_tbf); /* else, search for uplink tbf */ } else if ((usf_tbf = sched_select_uplink(pdch, require_gprs_only))) { LOGPDCH(pdch, DRLCMACSCHED, LOGL_DEBUG, "Received RTS for PDCH: FN=%d " @@ -478,7 +465,7 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts, /* Prio 1: select control message */ if ((msg = sched_select_ctrl_msg(pdch, fn, block_nr, &tbf_cand))) { - gsmtap_cat = PCU_GSMTAP_C_DL_CTRL; + gsmtap_cat = PCU_GSMTAP_C_DL_CTRL; } /* Prio 2: select data message for downlink */ else if((msg = sched_select_dl_data_msg(bts, pdch, fn, block_nr, req_mcs_kind, &tx_is_egprs))) { @@ -500,11 +487,10 @@ int gprs_rlcmac_rcv_rts_block(struct gprs_rlcmac_bts *bts, const unsigned num_tbfs = pdch->num_tbfs(GPRS_RLCMAC_DL_TBF) + pdch->num_tbfs(GPRS_RLCMAC_UL_TBF); bool skip_idle = (num_tbfs == 0); -#ifdef ENABLE_DIRECT_PHY - /* In DIRECT_PHY mode we want to always submit something to L1 in - * TRX0, since BTS is not preparing dummy bursts on idle TS for us */ - skip_idle = skip_idle && trx != 0; -#endif + + if (bts->gen_idle_blocks_C0) + skip_idle = skip_idle && trx != 0; + if (!skip_idle && (msg = sched_dummy())) { /* increase counter */ gsmtap_cat = PCU_GSMTAP_C_DL_DUMMY; |