[PATCH] osmo-pcu[master]: TBF: implement independent T31xx timers

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Max gerrit-no-reply at lists.osmocom.org
Mon Dec 4 11:53:19 UTC 2017


Review at  https://gerrit.osmocom.org/5158

TBF: implement independent T31xx timers

Previously TBF got single timer so the pending timer was automatically
cancelled when new one was scheduled. Let's make it more robust by
implementing independent T31 xx timers from 3GPP TS 44.060 §13.2 with
corresponding start/stop functions and counters.

N. B. - some timers are still used as before:
* T3169: changing would require changing test output
* T3193: changing causes segfault
* T0: used for assign/reject timeouts, have to be properly attributed
  and documented first

This will be fixed in follow-up patches.

Change-Id: I0305873ca47534f53441247217881da59625e1f7
Related: OS#2407
---
M src/tbf.cpp
M src/tbf.h
M src/tbf_dl.cpp
M tests/tbf/TbfTest.cpp
4 files changed, 146 insertions(+), 12 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/58/5158/1

diff --git a/src/tbf.cpp b/src/tbf.cpp
index 7b609c8..15e73f1 100644
--- a/src/tbf.cpp
+++ b/src/tbf.cpp
@@ -32,6 +32,7 @@
 
 extern "C" {
 #include <osmocom/core/msgb.h>
+#include <osmocom/core/utils.h>
 #include <osmocom/core/talloc.h>
 #include <osmocom/core/stats.h>
 }
@@ -163,6 +164,12 @@
 	n3105(0),
 	T(0),
 	num_T_exp(0),
+	num_T3169_exp(0),
+	num_T3191_exp(0),
+	num_T3193_exp(0),
+	num_T3195_exp(0),
+	num_T3197_exp(0),
+	num_T3199_exp(0),
 	fT(0),
 	num_fT_exp(0),
 	state(GPRS_RLCMAC_NULL),
@@ -183,6 +190,12 @@
 	 * Just set them to 0 like talloc_zero did */
 	memset(&pdch, 0, sizeof(pdch));
 	memset(&timer, 0, sizeof(timer));
+	memset(&T3169, 0, sizeof(T3169));
+	memset(&T3191, 0, sizeof(T3191));
+	memset(&T3193, 0, sizeof(T3193));
+	memset(&T3195, 0, sizeof(T3195));
+	memset(&T3197, 0, sizeof(T3197));
+	memset(&T3199, 0, sizeof(T3199));
 	memset(&m_rlc, 0, sizeof(m_rlc));
 	memset(&gsm_timer, 0, sizeof(gsm_timer));
 
@@ -465,6 +478,7 @@
 		     get_value_string(gprs_rlcmac_tbf_dl_ass_state_names,
 				      tbf->dl_ass_state));
 	tbf->stop_timer("freeing TBF");
+	tbf->stop_timers("freeing TBF");
 	/* TODO: Could/Should generate  bssgp_tx_llc_discarded */
 	tbf_unlink_pdch(tbf);
 	llist_del(&tbf->list());
@@ -550,9 +564,30 @@
 	osmo_timer_schedule(&tbf->timer, seconds, microseconds);
 }
 
-void gprs_rlcmac_tbf::stop_t3191()
+static inline void t_stop(const char *tbf_name, struct osmo_timer_list *t, uint16_t num, const char *reason)
 {
-	return stop_timer("T3191");
+	if (osmo_timer_pending(t)) {
+		LOGP(DRLCMAC, LOGL_DEBUG, "%s stopping timer T%u [%s]\n", tbf_name, num, reason);
+		osmo_timer_del(t);
+	}
+}
+
+#define STOP_T(nn) void gprs_rlcmac_tbf::stop_t##nn(const char *reason) { t_stop(tbf_name(this), &T##nn, nn, reason); }
+
+STOP_T(3169)
+STOP_T(3191)
+STOP_T(3193)
+STOP_T(3195)
+STOP_T(3197)
+STOP_T(3199)
+
+void gprs_rlcmac_tbf::stop_timers(const char *reason) {
+	stop_t3169(reason);
+	stop_t3191(reason);
+	stop_t3193(reason);
+	stop_t3195(reason);
+	stop_t3197(reason);
+	stop_t3199(reason);
 }
 
 void gprs_rlcmac_tbf::stop_timer(const char *reason)
@@ -563,6 +598,59 @@
 		osmo_timer_del(&timer);
 	}
 }
+
+static inline void tbf_timeout_free(struct gprs_rlcmac_tbf *tbf, uint16_t num, bool run_diag, bool free_tbf)
+{
+	LOGP(DRLCMAC, LOGL_NOTICE, "%s T%u timeout expired, freeing TBF\n",
+	     tbf_name(tbf), num, free_tbf ? "freeing" : "ignoring");
+
+	if (run_diag)
+		tbf->rlcmac_diag();
+
+	if (free_tbf)
+		tbf_free(tbf);
+}
+
+#define T_CBACK(nn, diag, free)				\
+	static void tbf_timer_cb##nn(void *_tbf) {	\
+		struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)_tbf; \
+		tbf_timeout_free(tbf, nn, diag, free);			\
+		tbf->num_T ## nn ## _exp++;				\
+	}
+
+T_CBACK(3169, true, true)
+T_CBACK(3191, true, true)
+T_CBACK(3193, false, true)
+T_CBACK(3195, true, true)
+T_CBACK(3197, false, false)
+T_CBACK(3199, false, false)
+
+typedef void (*t_cback)(void *_tbf);
+
+static inline void t_sched(struct gprs_rlcmac_tbf *tbf, struct osmo_timer_list *t, uint64_t *exp,
+			   uint16_t num, uint32_t sec, uint32_t microsec, t_cback cback, const char *reason)
+{
+	LOGP(DRLCMAC, LOGL_DEBUG, "%s %sstarting timer T%u [%s] with %u sec. %u microsec.\n",
+	     tbf_name(tbf), osmo_timer_pending(t) ? "re" : "", num, reason, sec, microsec);
+
+	t->data = tbf;
+	t->cb = cback;
+
+	*exp = 0;
+	osmo_timer_schedule(t, sec, microsec);
+}
+
+#define START_T(nn) \
+	void gprs_rlcmac_tbf::start_t##nn(uint32_t sec, uint32_t microsec, const char *reason) { \
+		t_sched(this, &T##nn, &num_T ## nn ##_exp, nn, sec, microsec, &tbf_timer_cb##nn, reason); \
+	}
+
+START_T(3169)
+START_T(3191)
+START_T(3193)
+START_T(3195)
+START_T(3197)
+START_T(3199)
 
 int gprs_rlcmac_tbf::check_polling(uint32_t fn, uint8_t ts,
 	uint32_t *poll_fn_, unsigned int *rrbp_)
@@ -685,7 +773,7 @@
 		if (n3105 == bts_data()->n3105) {
 			LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
 			set_state(GPRS_RLCMAC_RELEASING);
-			tbf_timer_start(this, 3195, bts_data()->t3195, 0, "MAX N3105 reached");
+			start_t3195(bts_data()->t3195, 0, "MAX N3105 reached");
 			bts->rlc_ass_failed();
 			bts->pua_poll_failed();
 			return;
@@ -707,7 +795,7 @@
 		if (n3105 == bts->bts_data()->n3105) {
 			LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
 			set_state(GPRS_RLCMAC_RELEASING);
-			tbf_timer_start(this, 3195, bts_data()->t3195, 0, "MAX N3105 reached");
+			start_t3195(bts_data()->t3195, 0, "MAX N3105 reached");
 			bts->rlc_ass_failed();
 			bts->pda_poll_failed();
 			return;
@@ -733,7 +821,7 @@
 		if (dl_tbf->n3105 == dl_tbf->bts->bts_data()->n3105) {
 			LOGP(DRLCMAC, LOGL_NOTICE, "- N3105 exceeded\n");
 			dl_tbf->set_state(GPRS_RLCMAC_RELEASING);
-			tbf_timer_start(dl_tbf, 3195, dl_tbf->bts_data()->t3195, 0, "MAX N3105 reached");
+			dl_tbf->start_t3195(dl_tbf->bts_data()->t3195, 0, "MAX N3105 reached");
 			bts->pkt_dl_ack_nack_poll_failed();
 			bts->rlc_ack_failed();
 			return;
@@ -1004,6 +1092,7 @@
 	tbf->handle_timeout();
 }
 
+/* FIXME: remove this once the switch over to start_t31*()/stop_t31*() is complete */
 void gprs_rlcmac_tbf::handle_timeout()
 {
 	LOGP(DRLCMAC, LOGL_DEBUG, "%s timer %u expired.\n",
@@ -1053,13 +1142,11 @@
 		}
 		break;
 	case 3169:
-	case 3191:
-	case 3195:
 		LOGP(DRLCMAC, LOGL_NOTICE, "%s T%d timeout during "
 			"transsmission\n", tbf_name(this), T);
 		rlcmac_diag();
 		/* fall through */
-	case 3193:
+	case 3193: /* FIXME: remove once issue with start_t3193() is resolved */
 		LOGP(DRLCMAC, LOGL_DEBUG,
 			"%s will be freed due to timeout\n", tbf_name(this));
 		/* free TBF */
diff --git a/src/tbf.h b/src/tbf.h
index 80249df..085c283 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -175,7 +175,19 @@
 	int update();
 	void handle_timeout();
 	void stop_timer(const char *reason);
-	void stop_t3191();
+	void stop_timers(const char *reason);
+	void stop_t3169(const char *reason);
+	void stop_t3191(const char *reason);
+	void stop_t3193(const char *reason);
+	void stop_t3195(const char *reason);
+	void stop_t3197(const char *reason);
+	void stop_t3199(const char *reason);
+	void start_t3169(uint32_t sec, uint32_t microsec, const char *reason);
+	void start_t3191(uint32_t sec, uint32_t microsec, const char *reason);
+	void start_t3193(uint32_t sec, uint32_t microsec, const char *reason);
+	void start_t3195(uint32_t sec, uint32_t microsec, const char *reason);
+	void start_t3197(uint32_t sec, uint32_t microsec, const char *reason);
+	void start_t3199(uint32_t sec, uint32_t microsec, const char *reason);
 	int establish_dl_tbf_on_pacch();
 
 	int check_polling(uint32_t fn, uint8_t ts,
@@ -248,6 +260,35 @@
 	struct osmo_timer_list	timer;
 	unsigned int T; /* Txxxx number */
 	unsigned int num_T_exp; /* number of consecutive T expirations */
+
+	/* Wait for reuse of USF and TFI(s) after the MS uplink assignment for this TBF is invalid. */
+	struct osmo_timer_list T3169;
+
+	/* Wait for reuse of TFI(s) after sending of the last RLC Data Block on this TBF.
+	   Wait for reuse of TFI(s) after sending the PACKET TBF RELEASE for an MBMS radio bearer. */
+	struct osmo_timer_list T3191;
+
+	/* Wait for reuse of TFI(s) after reception of the final PACKET DOWNLINK ACK/NACK from the
+	   MS for this TBF. */
+	struct osmo_timer_list T3193;
+
+	/* Wait for reuse of TFI(s) when there is no response from the MS
+	   (radio failure or cell change) for this TBF/MBMS radio bearer. */
+	struct osmo_timer_list T3195;
+
+	/* Wait for the indication from the MS that it has received needed system information
+	   messages. */
+	struct osmo_timer_list T3197;
+
+	/* Wait for reuse of MS_ID on an MBMS radio bearer. */
+	struct osmo_timer_list T3199;
+
+	uint64_t num_T3169_exp; /* number of consecutive T3169 expirations */
+	uint64_t num_T3191_exp; /* number of consecutive T3191 expirations */
+	uint64_t num_T3193_exp; /* number of consecutive T3193 expirations */
+	uint64_t num_T3195_exp; /* number of consecutive T3195 expirations */
+	uint64_t num_T3197_exp; /* number of consecutive T3197 expirations */
+	uint64_t num_T3199_exp; /* number of consecutive T3199 expirations */
 	
 	struct osmo_gsm_timer_list	gsm_timer;
 	unsigned int fT; /* fTxxxx number */
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index 73708f5..11c3af7 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -489,6 +489,7 @@
 {
 	/* stop pending timer */
 	stop_timer("assignment (DL-TBF)");
+	stop_timers("assignment (DL-TBF)");
 
 	/* check for downlink tbf:  */
 	if (old_tbf) {
@@ -658,7 +659,7 @@
 
 	/* reset N3105 */
 	n3105 = 0;
-	stop_t3191();
+	stop_t3191("ACK/NACK received");
 	poll_state = GPRS_RLCMAC_POLL_NONE;
 
 	return ack_recovered;
@@ -861,7 +862,7 @@
 			m_tx_counter = 0;
 			/* start timer whenever we send the final block */
 			if (is_final)
-				tbf_timer_start(this, 3191, bts_data()->t3191, 0, "final block (DL-TBF)");
+				start_t3191(bts_data()->t3191, 0, "final block (DL-TBF)");
 
 			clear_poll_timeout_flag();
 
@@ -1124,6 +1125,10 @@
 	set_state(GPRS_RLCMAC_WAIT_RELEASE);
 
 	/* start T3193 */
+	/* FIXME: using
+	   start_t3193(bts_data()->t3193_msec / 1000, (bts_data()->t3193_msec % 1000) * 1000, "release (DL-TBF)");
+	   causes segfault
+	*/
 	tbf_timer_start(this, 3193,
 		bts_data()->t3193_msec / 1000,
 			(bts_data()->t3193_msec % 1000) * 1000, "release (DL-TBF)");
diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp
index d4b51fe..23790de 100644
--- a/tests/tbf/TbfTest.cpp
+++ b/tests/tbf/TbfTest.cpp
@@ -51,7 +51,8 @@
 {
 	OSMO_ASSERT(tbf);
 	if (tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE))
-		OSMO_ASSERT(tbf->T == 3191 || tbf->T == 3193);
+		OSMO_ASSERT(osmo_timer_pending(&tbf->T3191) || tbf->T == 3193);
+	/* FIXME: use ... || osmo_timer_pending(&tbf->T3193) above once issue with start_t3193() is resolved */
 	if (tbf->state_is(GPRS_RLCMAC_RELEASING))
 		OSMO_ASSERT(tbf->T != 0);
 }

-- 
To view, visit https://gerrit.osmocom.org/5158
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0305873ca47534f53441247217881da59625e1f7
Gerrit-PatchSet: 1
Gerrit-Project: osmo-pcu
Gerrit-Branch: master
Gerrit-Owner: Max <msuraev at sysmocom.de>



More information about the gerrit-log mailing list