jolly has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmo-bts/+/35007?usp=email )
Change subject: Use polling based LAPDm with frame numbers
......................................................................
Use polling based LAPDm with frame numbers
Osmo-bts uses the new polling based LAPDm implementation.
The OML message NM_ATT_T200 is ignored, because T200 timeouts are set to
the minimal response time. Longer timeouts would cause lower throughput
in case of lost frames. Shorter timeouts would cause LAPDm to fail.
Related: OS#4074
Change-Id: Ic6d7902b13cf491daaa8752db78f9875387aeffd
---
M include/osmo-bts/bts.h
M include/osmo-bts/oml.h
M src/common/bts.c
M src/common/l1sap.c
M src/common/lchan.c
M src/common/oml.c
6 files changed, 100 insertions(+), 72 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/07/35007/1
diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h
index 985f4ed..7560598 100644
--- a/include/osmo-bts/bts.h
+++ b/include/osmo-bts/bts.h
@@ -241,7 +241,7 @@
int16_t boundary[6];
uint8_t intave;
} interference;
- unsigned int t200_ms[7];
+ unsigned int t200_fn[7];
unsigned int t3105_ms;
unsigned int t3115_ms; /* VGCS UPLINK GRANT repeat timer */
struct {
diff --git a/include/osmo-bts/oml.h b/include/osmo-bts/oml.h
index c35122e..ac1737c 100644
--- a/include/osmo-bts/oml.h
+++ b/include/osmo-bts/oml.h
@@ -68,7 +68,7 @@
int oml_mo_fom_ack_nack(const struct gsm_abis_mo *mo, uint8_t orig_msg_type,
uint8_t cause);
-extern const unsigned int oml_default_t200_ms[7];
+extern const unsigned int oml_default_t200_fn[7];
/* Transmit failure event report */
int oml_tx_failure_event_rep(const struct gsm_abis_mo *mo, enum abis_nm_severity
severity,
diff --git a/src/common/bts.c b/src/common/bts.c
index 7e7d8f0..12d3742 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -355,8 +355,8 @@
bts->max_ber10k_rach = 1707; /* 7 of 41 bits is Eb/N0 of 0 dB = 0.1707 */
bts->pcu.sock_path = talloc_strdup(bts, PCU_SOCK_DEFAULT);
bts->pcu.sock_wqueue_len_max = BTS_PCU_SOCK_WQUEUE_LEN_DEFAULT;
- for (i = 0; i < ARRAY_SIZE(bts->t200_ms); i++)
- bts->t200_ms[i] = oml_default_t200_ms[i];
+ for (i = 0; i < ARRAY_SIZE(bts->t200_fn); i++)
+ bts->t200_fn[i] = oml_default_t200_fn[i];
/* default RADIO_LINK_TIMEOUT */
bts->radio_link_timeout.oml = 32;
diff --git a/src/common/l1sap.c b/src/common/l1sap.c
index c599726..2a150b2 100644
--- a/src/common/l1sap.c
+++ b/src/common/l1sap.c
@@ -957,10 +957,10 @@
}
/* Common dequeueing function */
-static inline struct msgb *lapdm_phsap_dequeue_msg(struct lapdm_entity *le)
+static inline struct msgb *lapdm_phsap_dequeue_msg(struct lapdm_entity *le, uint32_t fn)
{
struct osmo_phsap_prim pp;
- if (lapdm_phsap_dequeue_prim(le, &pp) < 0)
+ if (lapdm_phsap_dequeue_prim_fn(le, &pp, fn) < 0)
return NULL;
return pp.oph.msg;
}
@@ -983,7 +983,7 @@
lchan->rep_acch.dl_facch[1].msg = NULL;
} else {
/* Fetch new FACCH from queue ... */
- if (lapdm_phsap_dequeue_prim(le, &pp) < 0)
+ if (lapdm_phsap_dequeue_prim_fn(le, &pp, fn) < 0)
return NULL;
msg = pp.oph.msg;
@@ -1013,7 +1013,7 @@
}
/* Special dequeueing function with SACCH repetition (3GPP TS 44.006, section 11) */
-static inline struct msgb *lapdm_phsap_dequeue_msg_sacch(struct gsm_lchan *lchan, struct
lapdm_entity *le)
+static inline struct msgb *lapdm_phsap_dequeue_msg_sacch(struct gsm_lchan *lchan, struct
lapdm_entity *le, uint32_t fn)
{
struct osmo_phsap_prim pp;
struct msgb *msg;
@@ -1037,7 +1037,7 @@
}
/* Fetch new repetition candidate from queue */
- if (lapdm_phsap_dequeue_prim(le, &pp) < 0)
+ if (lapdm_phsap_dequeue_prim_fn(le, &pp, fn) < 0)
return NULL;
msg = pp.oph.msg;
sapi = (msg->data[0] >> 2) & 0x07;
@@ -1148,9 +1148,9 @@
LOGPLCHAN(lchan, DL1P, LOGL_DEBUG, "DL-SACCH repetition: active =>
inactive\n");
lchan->rep_acch.dl_sacch_active = false;
}
- pp_msg = lapdm_phsap_dequeue_msg_sacch(lchan, le);
+ pp_msg = lapdm_phsap_dequeue_msg_sacch(lchan, le, fn);
} else {
- pp_msg = lapdm_phsap_dequeue_msg(le);
+ pp_msg = lapdm_phsap_dequeue_msg(le, fn);
}
} else {
if (lchan->ts->trx->bts->dtxd)
@@ -1159,7 +1159,7 @@
if (lchan->rep_acch.dl_facch_active && lchan->rsl_cmode !=
RSL_CMOD_SPD_SIGN)
pp_msg = lapdm_phsap_dequeue_msg_facch(lchan, le, fn);
else
- pp_msg = lapdm_phsap_dequeue_msg(le);
+ pp_msg = lapdm_phsap_dequeue_msg(le, fn);
lchan->tch.dtx_fr_hr_efr.dl_facch_stealing = (pp_msg != NULL);
}
if (!pp_msg) {
@@ -1802,9 +1802,18 @@
lchan_meas_handle_sacch(lchan, msg);
}
+ if (L1SAP_IS_LINK_SACCH(link_id))
+ le = &lchan->lapdm_ch.lapdm_acch;
+ else
+ le = &lchan->lapdm_ch.lapdm_dcch;
+
/* bad frame */
- if (len == 0)
+ if (len == 0) {
+ /* Notify current receive FN to lapdm. */
+ lapdm_t200_fn(le, fn);
+
return -EINVAL;
+ }
/* report first valid received frame to handover process */
if (lchan->ho.active == HANDOVER_WAIT_FRAME)
@@ -1825,11 +1834,6 @@
return 0;
}
- if (L1SAP_IS_LINK_SACCH(link_id))
- le = &lchan->lapdm_ch.lapdm_acch;
- else
- le = &lchan->lapdm_ch.lapdm_dcch;
-
if (check_for_first_ciphrd(lchan, data, len))
l1sap_tx_ciph_req(lchan->ts->trx, chan_nr, 1, 0);
@@ -1837,6 +1841,9 @@
msgb_pull_to_l2(msg);
lapdm_phsap_up(&l1sap->oph, le);
+ /* Notify current receive FN to lapdm. */
+ lapdm_t200_fn(le, fn);
+
/* don't free, because we forwarded data */
return 1;
}
@@ -1961,6 +1968,12 @@
LOGPLCGT(lchan, &g_time, DL1P, LOGL_DEBUG, "Rx TCH.ind\n");
}
+ /* Notify current receive FN to lapdm.
+ * TCH frames may be indicated before FACCH frames are indicated. To prevent T200
timeout before FACCH is
+ * received, substract one frame number, so that timeout is processed next time after
FACCH is received.
+ */
+ lapdm_t200_fn(&lchan->lapdm_ch.lapdm_dcch, (fn + GSM_MAX_FN - 1) % GSM_MAX_FN);
+
/* The ph_tch_param contained in the l1sap primitive may contain
* measurement data. If this data is present, forward it for
* processing */
diff --git a/src/common/lchan.c b/src/common/lchan.c
index 6178200..7539b26 100644
--- a/src/common/lchan.c
+++ b/src/common/lchan.c
@@ -57,41 +57,40 @@
};
/* prepare the per-SAPI T200 arrays for a given lchan */
-static int t200_by_lchan(int *t200_ms_dcch, int *t200_ms_acch, struct gsm_lchan *lchan)
+static int t200_by_lchan(int *t200_fn_dcch, int *t200_fn_acch, struct gsm_lchan *lchan)
{
struct gsm_bts *bts = lchan->ts->trx->bts;
- /* we have to compensate for the "RTS advance" due to the asynchronous
interface between
- * the BTS (LAPDm) and the PHY/L1 (OsmoTRX or DSP in case of
osmo-bts-{sysmo,lc15,oc2g,octphy} */
- int32_t fn_advance = bts_get_avg_fn_advance(bts);
- int32_t fn_advance_us = fn_advance * 4615;
- int fn_advance_ms = fn_advance_us / 1000;
-
- t200_ms_acch[DL_SAPI0] = bts->t200_ms[T200_SACCH_SDCCH] + fn_advance_ms;
- t200_ms_acch[DL_SAPI3] = bts->t200_ms[T200_SACCH_SDCCH] + fn_advance_ms;
-
- if (lchan->rep_acch_cap.dl_facch_all && lchan_is_tch(lchan)) {
- t200_ms_acch[DL_SAPI0] *= 2;
- t200_ms_acch[DL_SAPI3] *= 2;
- }
-
switch (lchan->type) {
case GSM_LCHAN_SDCCH:
- t200_ms_dcch[DL_SAPI0] = bts->t200_ms[T200_SDCCH] + fn_advance_ms;
- t200_ms_dcch[DL_SAPI3] = bts->t200_ms[T200_SDCCH_SAPI3] + fn_advance_ms;
+ t200_fn_dcch[DL_SAPI0] = bts->t200_fn[T200_SDCCH];
+ t200_fn_dcch[DL_SAPI3] = bts->t200_fn[T200_SDCCH_SAPI3];
+ t200_fn_acch[DL_SAPI0] = bts->t200_fn[T200_SACCH_SDCCH];
+ t200_fn_acch[DL_SAPI3] = bts->t200_fn[T200_SACCH_SDCCH];
break;
case GSM_LCHAN_TCH_F:
- t200_ms_dcch[DL_SAPI0] = bts->t200_ms[T200_FACCH_F] + fn_advance_ms;
- t200_ms_dcch[DL_SAPI3] = bts->t200_ms[T200_FACCH_F] + fn_advance_ms;
+ t200_fn_dcch[DL_SAPI0] = bts->t200_fn[T200_FACCH_F];
+ t200_fn_dcch[DL_SAPI3] = bts->t200_fn[T200_FACCH_F];
+ t200_fn_acch[DL_SAPI0] = bts->t200_fn[T200_SACCH_TCH_SAPI0];
+ t200_fn_acch[DL_SAPI3] = bts->t200_fn[T200_SACCH_TCH_SAPI3];
break;
case GSM_LCHAN_TCH_H:
- t200_ms_dcch[DL_SAPI0] = bts->t200_ms[T200_FACCH_H] + fn_advance_ms;
- t200_ms_dcch[DL_SAPI3] = bts->t200_ms[T200_FACCH_H] + fn_advance_ms;
+ t200_fn_dcch[DL_SAPI0] = bts->t200_fn[T200_FACCH_H];
+ t200_fn_dcch[DL_SAPI3] = bts->t200_fn[T200_FACCH_H];
+ t200_fn_acch[DL_SAPI0] = bts->t200_fn[T200_SACCH_TCH_SAPI0];
+ t200_fn_acch[DL_SAPI3] = bts->t200_fn[T200_SACCH_TCH_SAPI3];
break;
default:
/* Channels such as CCCH don't use lapdm DL, and hence no T200 is needed */
return -1;
}
+
+ /* Add time of two extra messages frames. */
+ if (lchan->rep_acch_cap.dl_facch_all && lchan_is_tch(lchan)) {
+ t200_fn_acch[DL_SAPI0] += 104 * 2;
+ t200_fn_acch[DL_SAPI3] += 104 * 2;
+ }
+
return 0;
}
@@ -152,17 +151,17 @@
int lchan_init_lapdm(struct gsm_lchan *lchan)
{
struct lapdm_channel *lc = &lchan->lapdm_ch;
- int t200_ms_dcch[_NR_DL_SAPI], t200_ms_acch[_NR_DL_SAPI];
+ int t200_fn_dcch[_NR_DL_SAPI], t200_fn_acch[_NR_DL_SAPI];
- if (t200_by_lchan(t200_ms_dcch, t200_ms_acch, lchan) == 0) {
+ if (t200_by_lchan(t200_fn_dcch, t200_fn_acch, lchan) == 0) {
LOGPLCHAN(lchan, DLLAPD, LOGL_DEBUG,
- "Setting T200 D0=%u, D3=%u, S0=%u, S3=%u (all in ms)\n",
- t200_ms_dcch[DL_SAPI0], t200_ms_dcch[DL_SAPI3],
- t200_ms_acch[DL_SAPI0], t200_ms_acch[DL_SAPI3]);
- lapdm_channel_init3(lc, LAPDM_MODE_BTS, t200_ms_dcch, t200_ms_acch, lchan->type,
- gsm_lchan_name(lchan));
+ "Setting T200 D0=%u, D3=%u, S0=%u, S3=%u (all in frames)\n",
+ t200_fn_dcch[DL_SAPI0], t200_fn_dcch[DL_SAPI3],
+ t200_fn_acch[DL_SAPI0], t200_fn_acch[DL_SAPI3]);
+ lapdm_channel_init3(lc, LAPDM_MODE_BTS, NULL, NULL, lchan->type,
gsm_lchan_name(lchan));
lapdm_channel_set_flags(lc, LAPDM_ENT_F_POLLING_ONLY);
lapdm_channel_set_l1(lc, NULL, lchan);
+ lapdm_channel_set_t200_fn(lc, t200_fn_dcch, t200_fn_acch);
}
/* We still need to set Rx callback to receive RACH requests: */
lapdm_channel_set_l3(lc, lapdm_rll_tx_cb, lchan);
diff --git a/src/common/oml.c b/src/common/oml.c
index 701f5f3..58fa23d 100644
--- a/src/common/oml.c
+++ b/src/common/oml.c
@@ -525,16 +525,19 @@
return oml_mo_send_msg(mo, nmsg, NM_MT_SW_ACTIVATED_REP);
}
-/* The defaults below correspond to various sources/recommendations that could be found
online.
- * The BSC should override this via OML anyway. */
-const unsigned int oml_default_t200_ms[7] = {
- [T200_SDCCH] = 1000,
- [T200_FACCH_F] = 1000,
- [T200_FACCH_H] = 1000,
- [T200_SACCH_TCH_SAPI0] = 2000,
- [T200_SACCH_SDCCH] = 2000,
- [T200_SDCCH_SAPI3] = 1000,
- [T200_SACCH_TCH_SAPI3] = 2000,
+/* The defaults below correspond to the number of frames until a response from the MS is
expected.
+ * It defines the duration between the frame number when a message is sent (first frame)
and when the response is
+ * received (first frame). On SACCH the duration is two frames, because SAPI0 and SAPI3
are are transmitted in
+ * alternating order. On DCCH with SAPI3 the duration is two seconds, because SAPI0 has
priority over SAPI3.
+ */
+const unsigned int oml_default_t200_fn[7] = {
+ [T200_SDCCH] = 4+32,
+ [T200_FACCH_F] = 8+9,
+ [T200_FACCH_H] = 6+10,
+ [T200_SACCH_TCH_SAPI0] = 79+25+104,
+ [T200_SACCH_SDCCH] = 4+32+51,
+ [T200_SDCCH_SAPI3] = 4+32+408, /* two seconds */
+ [T200_SACCH_TCH_SAPI3] = 79+25+104,
};
/* 3GPP TS 52.021 §8.11.1 Get Attributes has been received */
@@ -677,25 +680,22 @@
}
/* 9.4.53 T200 */
- if (TLVP_PRES_LEN(&tp, NM_ATT_T200, ARRAY_SIZE(bts->t200_ms))) {
- payload = TLVP_VAL(&tp, NM_ATT_T200);
- for (i = 0; i < ARRAY_SIZE(bts->t200_ms); i++) {
- uint32_t t200_ms = payload[i] * abis_nm_t200_ms[i];
+ if (TLVP_PRES_LEN(&tp, NM_ATT_T200, ARRAY_SIZE(bts->t200_fn))) {
#if 0
- bts->t200_ms[i] = t200_ms;
- DEBUGPFOH(DOML, foh, "T200[%u]: OML=%u, mult=%u => %u ms\n",
+ payload = TLVP_VAL(&tp, NM_ATT_T200);
+ for (i = 0; i < ARRAY_SIZE(bts->t200_fn); i++) {
+ uint32_t t200_ms = payload[i] * abis_nm_t200_ms[i];
+ uint32_t t200_fn = t200_ms * 1000 + (GSM_TDMA_FN_DURATION_uS - 1) /
GSM_TDMA_FN_DURATION_uS;
+ /* Values must not be less than absolute minimum. */
+ if (oml_default_t200_fn[i] <= t200_fn)
+ bts->t200_fn[i] = t200_fn;
+ else
+ bts->t200_fn[i] = oml_default_t200_fn[i];
+ DEBUGPFOH(DOML, foh, "T200[%u]: OML=%u, mult=%u => %u ms -> %u fn\n",
i, payload[i], abis_nm_t200_ms[i],
- bts->t200_ms[i]);
-#else
- /* we'd rather use the 1s/2s (long) defaults by
- * libosmocore, as we appear to have some bug(s)
- * related to handling T200 expiration in
- * libosmogsm lapd(m) code? */
- LOGPFOH(DOML, LOGL_NOTICE, foh, "Ignoring T200[%u] (%u ms)
"
- "as sent by BSC due to suspected LAPDm
bug!\n",
- i, t200_ms);
-#endif
+ t200_ms, bts->t200_fn[i]);
}
+#endif
}
/* 9.4.31 Maximum Timing Advance */
--
To view, visit
https://gerrit.osmocom.org/c/osmo-bts/+/35007?usp=email
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: Ic6d7902b13cf491daaa8752db78f9875387aeffd
Gerrit-Change-Number: 35007
Gerrit-PatchSet: 1
Gerrit-Owner: jolly <andreas(a)eversberg.eu>
Gerrit-MessageType: newchange