<p>pespin <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-pcu/+/21178">View Change</a></p><div style="white-space:pre-wrap">Approvals:
laforge: Looks good to me, but someone else must approve
neels: Looks good to me, but someone else must approve
pespin: Looks good to me, approved
Jenkins Builder: Verified
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Support multiplexing of GPRS and EGPRS TBFs in one PDCH<br><br>There are some restrictions to have both GPRS-only and EGPRS MS attached<br>to the same MS:<br>* Any MS needs to be able to successfully decode a DL block at least<br> every 18 DL blocks (360 ms). That means a Dl block with CS1-4 must be<br> sent at least once during that time.<br>* Any MS needs to be able to decode USF targeting it. GPRS-only MS can<br> successfully decode USF from DL blocks using GMSK: CS1-4 and MCS1-4.<br><br>In this patch, if USF of a GPRS-only MS is selected, then all DL EGPRS<br>TBFs are discarded from data block selection. However, this logic can be<br>further improved later by still allowing selection of DL EGPRS TBFs and<br>then forcing construction of a DL EGPRS data block using MCS1-4.<br><br>Sources:<br>* 3GPP TS 03.64 version 8.12.0 "6.6.4.1.1.2 Multiplexing of GPRS and EGPRS MSs"<br>* 3GPP TS 05.08 version 8.23.0 "10.2.2 BTS output power"<br><br>Related: OS#4544<br>Change-Id: Ib4991c864eda6864533363443f76ae5d999532ae<br>---<br>M src/gprs_rlcmac_sched.cpp<br>M src/pdch.cpp<br>M src/pdch.h<br>3 files changed, 96 insertions(+), 29 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp</span><br><span>index 97806d9..537929b 100644</span><br><span>--- a/src/gprs_rlcmac_sched.cpp</span><br><span>+++ b/src/gprs_rlcmac_sched.cpp</span><br><span>@@ -89,11 +89,10 @@</span><br><span> return poll_fn;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static uint8_t sched_select_uplink(uint8_t trx, uint8_t ts, uint32_t fn,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t block_nr, struct gprs_rlcmac_pdch *pdch)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct gprs_rlcmac_ul_tbf *sched_select_uplink(uint8_t trx, uint8_t ts, uint32_t fn,</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t block_nr, struct gprs_rlcmac_pdch *pdch, bool require_gprs_only)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- struct gprs_rlcmac_ul_tbf *tbf;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t usf = 0x07;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_ul_tbf *tbf = NULL;</span><br><span> uint8_t i, tfi;</span><br><span> </span><br><span> /* select uplink resource */</span><br><span>@@ -110,18 +109,20 @@</span><br><span> if (tbf->state_is_not(GPRS_RLCMAC_FLOW))</span><br><span> continue;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if (require_gprs_only && tbf->is_egprs_enabled())</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* use this USF */</span><br><span style="color: hsl(0, 100%, 40%);">- usf = tbf->m_usf[ts];</span><br><span> LOGP(DRLCMACSCHED, LOGL_DEBUG, "Received RTS for PDCH: TRX=%d "</span><br><span> "TS=%d FN=%d block_nr=%d scheduling USF=%d for "</span><br><span> "required uplink resource of UL TFI=%d\n", trx, ts, fn,</span><br><span style="color: hsl(0, 100%, 40%);">- block_nr, usf, tfi);</span><br><span style="color: hsl(120, 100%, 40%);">+ block_nr, tbf->m_usf[ts], tfi);</span><br><span> /* next TBF to handle resource is the next one */</span><br><span> pdch->next_ul_tfi = (tfi + 1) & 31;</span><br><span> break;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- return usf;</span><br><span style="color: hsl(120, 100%, 40%);">+ return tbf;</span><br><span> }</span><br><span> </span><br><span> struct msgb *sched_app_info(struct gprs_rlcmac_tbf *tbf) {</span><br><span>@@ -273,7 +274,7 @@</span><br><span> </span><br><span> static struct msgb *sched_select_downlink(struct gprs_rlcmac_bts *bts,</span><br><span> uint8_t trx, uint8_t ts, uint32_t fn,</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t block_nr, struct gprs_rlcmac_pdch *pdch, bool *is_egprs)</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t block_nr, struct gprs_rlcmac_pdch *pdch, enum mcs_kind req_mcs_kind, bool *is_egprs)</span><br><span> {</span><br><span> struct msgb *msg = NULL;</span><br><span> struct gprs_rlcmac_dl_tbf *tbf, *prio_tbf = NULL;</span><br><span>@@ -301,6 +302,13 @@</span><br><span> if (tbf->m_wait_confirm)</span><br><span> continue;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* If a GPRS (CS1-4) Dl block is required, skip EGPRS(_GSMK) tbfs: */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (req_mcs_kind == GPRS && tbf->is_egprs_enabled())</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* TODO: If a GPRS (CS1-4/MCS1-4) Dl block is required, downgrade MCS below instead of skipping */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (req_mcs_kind == EGPRS_GMSK && (tbf->is_egprs_enabled() || tbf->ms()->mode() != GPRS))</span><br><span style="color: hsl(120, 100%, 40%);">+ continue;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> age = tbf->frames_since_last_poll(fn);</span><br><span> </span><br><span> /* compute priority */</span><br><span>@@ -385,12 +393,15 @@</span><br><span> struct gprs_rlcmac_pdch *pdch;</span><br><span> struct gprs_rlcmac_tbf *poll_tbf = NULL, *dl_ass_tbf = NULL,</span><br><span> *ul_ass_tbf = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gprs_rlcmac_ul_tbf *usf_tbf;</span><br><span> struct gprs_rlcmac_ul_tbf *ul_ack_tbf = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">- uint8_t usf = 0x7;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t usf;</span><br><span> struct msgb *msg = NULL;</span><br><span> uint32_t poll_fn, sba_fn;</span><br><span> enum pcu_gsmtap_category gsmtap_cat;</span><br><span style="color: hsl(0, 100%, 40%);">- bool is_egprs = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool tx_is_egprs = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool require_gprs_only;</span><br><span style="color: hsl(120, 100%, 40%);">+ enum mcs_kind req_mcs_kind; /* Restrict CS/MCS if DL Data block is to be sent */</span><br><span> </span><br><span> if (trx >= 8 || ts >= 8)</span><br><span> return -EINVAL;</span><br><span>@@ -405,47 +416,79 @@</span><br><span> /* store last frame number of RTS */</span><br><span> pdch->last_rts_fn = fn;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* require_gprs_only: Prioritize USF for GPRS-only MS here,</span><br><span style="color: hsl(120, 100%, 40%);">+ * since anyway we'll need to tx a Dl block with CS1-4 due to</span><br><span style="color: hsl(120, 100%, 40%);">+ * synchronization requirements. See 3GPP TS 03.64 version</span><br><span style="color: hsl(120, 100%, 40%);">+ * 8.12.0</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ require_gprs_only = (pdch->fn_without_cs14 == MS_RESYNC_NUM_FRAMES - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (require_gprs_only) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DRLCMACSCHED, LOGL_DEBUG, "TRX=%d TS=%d FN=%d "</span><br><span style="color: hsl(120, 100%, 40%);">+ "synchronization frame (every 18 frames), only CS1-4 allowed",</span><br><span style="color: hsl(120, 100%, 40%);">+ trx, ts, fn);</span><br><span style="color: hsl(120, 100%, 40%);">+ req_mcs_kind = GPRS; /* only GPRS CS1-4 allowed, all MS need to be able to decode it */</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ req_mcs_kind = EGPRS; /* all kinds are fine */</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> poll_fn = sched_poll(bts->bts, trx, ts, fn, block_nr, &poll_tbf, &ul_ass_tbf,</span><br><span> &dl_ass_tbf, &ul_ack_tbf);</span><br><span> /* check uplink resource for polling */</span><br><span style="color: hsl(0, 100%, 40%);">- if (poll_tbf)</span><br><span style="color: hsl(120, 100%, 40%);">+ if (poll_tbf) {</span><br><span> LOGP(DRLCMACSCHED, LOGL_DEBUG, "Received RTS for PDCH: TRX=%d "</span><br><span> "TS=%d FN=%d block_nr=%d scheduling free USF for "</span><br><span> "polling at FN=%d of %s\n", trx, ts, fn,</span><br><span> block_nr, poll_fn,</span><br><span> tbf_name(poll_tbf));</span><br><span style="color: hsl(0, 100%, 40%);">- /* use free USF */</span><br><span style="color: hsl(120, 100%, 40%);">+ usf = USF_UNUSED;</span><br><span> /* else. check for sba */</span><br><span style="color: hsl(0, 100%, 40%);">- else if ((sba_fn = bts->bts->sba()->sched(trx, ts, fn, block_nr) != 0xffffffff))</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if ((sba_fn = bts->bts->sba()->sched(trx, ts, fn, block_nr) != 0xffffffff)) {</span><br><span> LOGP(DRLCMACSCHED, LOGL_DEBUG, "Received RTS for PDCH: TRX=%d "</span><br><span> "TS=%d FN=%d block_nr=%d scheduling free USF for "</span><br><span> "single block allocation at FN=%d\n", trx, ts, fn,</span><br><span> block_nr, sba_fn);</span><br><span style="color: hsl(0, 100%, 40%);">- /* use free USF */</span><br><span style="color: hsl(120, 100%, 40%);">+ usf = USF_UNUSED;</span><br><span> /* else, we search for uplink resource */</span><br><span style="color: hsl(0, 100%, 40%);">- else</span><br><span style="color: hsl(0, 100%, 40%);">- usf = sched_select_uplink(trx, ts, fn, block_nr, pdch);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Prio 1: select control message */</span><br><span style="color: hsl(0, 100%, 40%);">- msg = sched_select_ctrl_msg(trx, ts, fn, block_nr, pdch, ul_ass_tbf,</span><br><span style="color: hsl(0, 100%, 40%);">- dl_ass_tbf, ul_ack_tbf);</span><br><span style="color: hsl(0, 100%, 40%);">- gsmtap_cat = PCU_GSMTAP_C_DL_CTRL;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Prio 2: select data message for downlink */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!msg) {</span><br><span style="color: hsl(0, 100%, 40%);">- msg = sched_select_downlink(bts, trx, ts, fn, block_nr, pdch, &is_egprs);</span><br><span style="color: hsl(0, 100%, 40%);">- gsmtap_cat = is_egprs ? PCU_GSMTAP_C_DL_DATA_EGPRS : PCU_GSMTAP_C_DL_DATA_GPRS;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ usf_tbf = sched_select_uplink(trx, ts, fn, block_nr, pdch, require_gprs_only);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (usf_tbf) {</span><br><span style="color: hsl(120, 100%, 40%);">+ usf = usf_tbf->m_usf[ts];</span><br><span style="color: hsl(120, 100%, 40%);">+ /* If MS selected for USF is GPRS-only, then it will</span><br><span style="color: hsl(120, 100%, 40%);">+ * only be able to read USF if dl block uses GMSK</span><br><span style="color: hsl(120, 100%, 40%);">+ * (CS1-4, MCS1-4)</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (req_mcs_kind == EGPRS && usf_tbf->ms()->mode() != EGPRS)</span><br><span style="color: hsl(120, 100%, 40%);">+ req_mcs_kind = EGPRS_GMSK;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ usf = USF_UNUSED;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Prio 1: select control message */</span><br><span style="color: hsl(120, 100%, 40%);">+ if ((msg = sched_select_ctrl_msg(trx, ts, fn, block_nr, pdch, ul_ass_tbf,</span><br><span style="color: hsl(120, 100%, 40%);">+ dl_ass_tbf, ul_ack_tbf))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gsmtap_cat = PCU_GSMTAP_C_DL_CTRL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Prio 2: select data message for downlink */</span><br><span style="color: hsl(120, 100%, 40%);">+ else if((msg = sched_select_downlink(bts, trx, ts, fn, block_nr, pdch, req_mcs_kind, &tx_is_egprs))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gsmtap_cat = tx_is_egprs ? PCU_GSMTAP_C_DL_DATA_EGPRS :</span><br><span style="color: hsl(120, 100%, 40%);">+ PCU_GSMTAP_C_DL_DATA_GPRS;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> /* Prio 3: send dummy contol message */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!msg) {</span><br><span style="color: hsl(120, 100%, 40%);">+ else if ((msg = sched_dummy())) {</span><br><span> /* increase counter */</span><br><span> msg = sched_dummy();</span><br><span> gsmtap_cat = PCU_GSMTAP_C_DL_DUMMY;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ return -ENOMEM;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (!msg)</span><br><span style="color: hsl(0, 100%, 40%);">- return -ENOMEM;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (tx_is_egprs && pdch->has_gprs_only_tbf_attached()) {</span><br><span style="color: hsl(120, 100%, 40%);">+ pdch->fn_without_cs14 += 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ pdch->fn_without_cs14 = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* msg is now available */</span><br><span> bts->bts->do_rate_ctr_add(CTR_RLC_DL_BYTES, msg->data_len);</span><br><span> </span><br><span>diff --git a/src/pdch.cpp b/src/pdch.cpp</span><br><span>index ff13477..a7dd2aa 100644</span><br><span>--- a/src/pdch.cpp</span><br><span>+++ b/src/pdch.cpp</span><br><span>@@ -944,6 +944,22 @@</span><br><span> m_assigned_usf, m_assigned_tfi[tbf->direction]);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+bool gprs_rlcmac_pdch::has_gprs_only_tbf_attached() const</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int i;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int j;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < sizeof(m_assigned_tfi[0]); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ for (j = 0; j < 2; j++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (m_assigned_tfi[j] & (1UL << i)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ gprs_rlcmac_tbf *tbf = m_tbfs[j][i];</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!tbf->is_egprs_enabled())</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void gprs_rlcmac_pdch::reserve(enum gprs_rlcmac_tbf_direction dir)</span><br><span> {</span><br><span> m_num_reserved[dir] += 1;</span><br><span>diff --git a/src/pdch.h b/src/pdch.h</span><br><span>index 1c0993f..5185045 100644</span><br><span>--- a/src/pdch.h</span><br><span>+++ b/src/pdch.h</span><br><span>@@ -40,6 +40,10 @@</span><br><span> #define PTCCH_TAI_NUM 16 /*!< Number of PTCCH/U slots and thus TA Indexes */</span><br><span> #define PTCCH_PADDING 0x2b /*!< PTCCH/D messages need to be padded to 23 octets */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define USF_UNUSED 0x07</span><br><span style="color: hsl(120, 100%, 40%);">+/* 3GPP TS 05.08 version 8.23.0 "10.2.2 BTS output power". 360 ms */</span><br><span style="color: hsl(120, 100%, 40%);">+#define MS_RESYNC_NUM_FRAMES 18</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*</span><br><span> * PDCH instance</span><br><span> */</span><br><span>@@ -83,6 +87,8 @@</span><br><span> </span><br><span> uint8_t assigned_usf() const;</span><br><span> uint32_t assigned_tfi(enum gprs_rlcmac_tbf_direction dir) const;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ bool has_gprs_only_tbf_attached() const;</span><br><span> #endif</span><br><span> </span><br><span> uint8_t m_is_enabled; /* TS is enabled */</span><br><span>@@ -92,6 +98,8 @@</span><br><span> uint8_t next_ctrl_prio; /* next kind of ctrl message to schedule */</span><br><span> struct llist_head paging_list; /* list of paging messages */</span><br><span> uint32_t last_rts_fn; /* store last frame number of RTS */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* store number of contiguous frame number where a DL block was transmitted which can be decoded by GPRS-only MS */</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t fn_without_cs14;</span><br><span> </span><br><span> /* PTCCH (Packet Timing Advance Control Channel) */</span><br><span> uint8_t ptcch_msg[GSM_MACBLOCK_LEN]; /* 'ready to use' PTCCH/D message */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-pcu/+/21178">change 21178</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-pcu/+/21178"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-pcu </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ib4991c864eda6864533363443f76ae5d999532ae </div>
<div style="display:none"> Gerrit-Change-Number: 21178 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>