aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gprs_ms.cpp57
-rw-r--r--src/gprs_ms.h21
-rw-r--r--tests/ms/MsTest.cpp70
-rw-r--r--tests/ms/MsTest.err7
-rw-r--r--tests/ms/MsTest.ok4
5 files changed, 153 insertions, 6 deletions
diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp
index d6520c31..f5b92d2f 100644
--- a/src/gprs_ms.cpp
+++ b/src/gprs_ms.cpp
@@ -40,11 +40,9 @@ struct GprsMsDefaultCallback: public GprsMs::Callback {
static GprsMsDefaultCallback gprs_default_cb;
-
-GprsMs::Guard::Guard(GprsMs *ms) : m_ms(ms)
+GprsMs::Guard::Guard(GprsMs *ms) :
+ m_ms(ms ? ms->ref() : NULL)
{
- if (m_ms)
- m_ms->ref();
}
GprsMs::Guard::~Guard()
@@ -53,6 +51,19 @@ GprsMs::Guard::~Guard()
m_ms->unref();
}
+void GprsMs::timeout(void *priv_)
+{
+ GprsMs *ms = static_cast<GprsMs *>(priv_);
+
+ LOGP(DRLCMAC, LOGL_INFO, "Timeout for MS object, TLLI = 0x%08x\n",
+ ms->tlli());
+
+ if (ms->m_timer.data) {
+ ms->m_timer.data = NULL;
+ ms->unref();
+ }
+}
+
GprsMs::GprsMs(uint32_t tlli) :
m_cb(&gprs_default_cb),
m_ul_tbf(NULL),
@@ -68,12 +79,17 @@ GprsMs::GprsMs(uint32_t tlli) :
LOGP(DRLCMAC, LOGL_INFO, "Creating MS object, TLLI = 0x%08x\n", tlli);
m_imsi[0] = 0;
+ memset(&m_timer, 0, sizeof(m_timer));
+ m_timer.cb = GprsMs::timeout;
}
GprsMs::~GprsMs()
{
LOGP(DRLCMAC, LOGL_INFO, "Destroying MS object, TLLI = 0x%08x\n", tlli());
+ if (osmo_timer_pending(&m_timer))
+ osmo_timer_del(&m_timer);
+
if (m_ul_tbf) {
m_ul_tbf->set_ms(NULL);
m_ul_tbf = NULL;
@@ -99,9 +115,10 @@ void GprsMs::operator delete(void* p)
talloc_free(p);
}
-void GprsMs::ref()
+GprsMs *GprsMs::ref()
{
m_ref += 1;
+ return this;
}
void GprsMs::unref()
@@ -112,6 +129,27 @@ void GprsMs::unref()
update_status();
}
+void GprsMs::start_timer()
+{
+ if (m_delay == 0)
+ return;
+
+ if (!m_timer.data)
+ m_timer.data = ref();
+
+ osmo_timer_schedule(&m_timer, m_delay, 0);
+}
+
+void GprsMs::stop_timer()
+{
+ if (!m_timer.data)
+ return;
+
+ osmo_timer_del(&m_timer);
+ m_timer.data = NULL;
+ unref();
+}
+
void GprsMs::attach_tbf(struct gprs_rlcmac_tbf *tbf)
{
if (tbf->direction == GPRS_RLCMAC_DL_TBF)
@@ -134,6 +172,9 @@ void GprsMs::attach_ul_tbf(struct gprs_rlcmac_ul_tbf *tbf)
detach_tbf(m_ul_tbf);
m_ul_tbf = tbf;
+
+ if (tbf)
+ stop_timer();
}
void GprsMs::attach_dl_tbf(struct gprs_rlcmac_dl_tbf *tbf)
@@ -150,6 +191,9 @@ void GprsMs::attach_dl_tbf(struct gprs_rlcmac_dl_tbf *tbf)
detach_tbf(m_dl_tbf);
m_dl_tbf = tbf;
+
+ if (tbf)
+ stop_timer();
}
void GprsMs::detach_tbf(gprs_rlcmac_tbf *tbf)
@@ -167,6 +211,9 @@ void GprsMs::detach_tbf(gprs_rlcmac_tbf *tbf)
if (tbf->ms() == this)
tbf->set_ms(NULL);
+ if (!m_dl_tbf && !m_dl_tbf)
+ start_timer();
+
update_status();
}
diff --git a/src/gprs_ms.h b/src/gprs_ms.h
index 9c3acb4f..db55badf 100644
--- a/src/gprs_ms.h
+++ b/src/gprs_ms.h
@@ -25,6 +25,11 @@ struct gprs_rlcmac_dl_tbf;
struct gprs_rlcmac_ul_tbf;
#include "cxx_linuxlist.h"
+
+extern "C" {
+ #include <osmocom/core/timer.h>
+}
+
#include <stdint.h>
#include <stddef.h>
@@ -62,6 +67,8 @@ public:
uint8_t ta() const;
void set_ta(uint8_t ta);
+ void set_timeout(unsigned secs);
+
void attach_tbf(gprs_rlcmac_tbf *tbf);
void attach_ul_tbf(gprs_rlcmac_ul_tbf *tbf);
void attach_dl_tbf(gprs_rlcmac_dl_tbf *tbf);
@@ -76,10 +83,15 @@ public:
LListHead<GprsMs>& list() {return this->m_list;}
const LListHead<GprsMs>& list() const {return this->m_list;}
+ /* internal use */
+ static void timeout(void *priv_);
+
protected:
void update_status();
- void ref();
+ GprsMs *ref();
void unref();
+ void start_timer();
+ void stop_timer();
private:
Callback * m_cb;
@@ -96,6 +108,8 @@ private:
bool m_is_idle;
int m_ref;
LListHead<GprsMs> m_list;
+ struct osmo_timer_list m_timer;
+ unsigned m_delay;
};
inline uint32_t GprsMs::tlli() const
@@ -120,3 +134,8 @@ inline uint8_t GprsMs::ta() const
{
return m_ta;
}
+
+inline void GprsMs::set_timeout(unsigned secs)
+{
+ m_delay = secs;
+}
diff --git a/tests/ms/MsTest.cpp b/tests/ms/MsTest.cpp
index 9c8ec2c3..bb9e21bf 100644
--- a/tests/ms/MsTest.cpp
+++ b/tests/ms/MsTest.cpp
@@ -36,6 +36,7 @@ extern "C" {
}
#include <errno.h>
+#include <unistd.h>
void *tall_pcu_ctx;
int16_t spoof_mnc = 0, spoof_mcc = 0;
@@ -399,6 +400,74 @@ static void test_ms_storage()
printf("=== end %s ===\n", __func__);
}
+static void test_ms_timeout()
+{
+ uint32_t tlli = 0xffeeddbb;
+ gprs_rlcmac_dl_tbf *dl_tbf;
+ gprs_rlcmac_ul_tbf *ul_tbf;
+ GprsMs *ms;
+ static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN;
+
+ struct MyCallback: public GprsMs::Callback {
+ virtual void ms_idle(class GprsMs *ms) {
+ OSMO_ASSERT(ms->is_idle());
+ printf(" ms_idle() was called\n");
+ last_cb = IS_IDLE;
+ }
+ virtual void ms_active(class GprsMs *ms) {
+ OSMO_ASSERT(!ms->is_idle());
+ printf(" ms_active() was called\n");
+ last_cb = IS_ACTIVE;
+ }
+ } cb;
+
+ printf("=== start %s ===\n", __func__);
+
+ ms = new GprsMs(tlli);
+ ms->set_callback(&cb);
+ ms->set_timeout(1);
+
+ OSMO_ASSERT(ms->is_idle());
+
+ dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
+ dl_tbf->direction = GPRS_RLCMAC_DL_TBF;
+ ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
+ ul_tbf->direction = GPRS_RLCMAC_UL_TBF;
+
+ OSMO_ASSERT(last_cb == UNKNOWN);
+
+ ms->attach_tbf(ul_tbf);
+ OSMO_ASSERT(!ms->is_idle());
+ OSMO_ASSERT(last_cb == IS_ACTIVE);
+
+ last_cb = UNKNOWN;
+
+ ms->attach_tbf(dl_tbf);
+ OSMO_ASSERT(!ms->is_idle());
+ OSMO_ASSERT(last_cb == UNKNOWN);
+
+ ms->detach_tbf(ul_tbf);
+ OSMO_ASSERT(!ms->is_idle());
+ OSMO_ASSERT(last_cb == UNKNOWN);
+
+ ms->detach_tbf(dl_tbf);
+ OSMO_ASSERT(!ms->is_idle());
+ OSMO_ASSERT(last_cb == UNKNOWN);
+
+ usleep(1100000);
+ osmo_timers_update();
+
+ OSMO_ASSERT(ms->is_idle());
+ OSMO_ASSERT(last_cb == IS_IDLE);
+
+ last_cb = UNKNOWN;
+ delete ms;
+ talloc_free(dl_tbf);
+ talloc_free(ul_tbf);
+
+ printf("=== end %s ===\n", __func__);
+}
+
static const struct log_info_cat default_categories[] = {
{"DPCU", "", "GPRS Packet Control Unit (PCU)", LOGL_INFO, 1},
};
@@ -437,6 +506,7 @@ int main(int argc, char **argv)
test_ms_replace_tbf();
test_ms_change_tlli();
test_ms_storage();
+ test_ms_timeout();
if (getenv("TALLOC_REPORT_FULL"))
talloc_report_full(tall_pcu_ctx, stderr);
diff --git a/tests/ms/MsTest.err b/tests/ms/MsTest.err
index 86dbb5b0..9e9df557 100644
--- a/tests/ms/MsTest.err
+++ b/tests/ms/MsTest.err
@@ -47,3 +47,10 @@ Destroying MS object, TLLI = 0xffeeddbb
Attaching TBF to MS object, TLLI = 0xffeeddbc, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL)
Detaching TBF from MS object, TLLI = 0xffeeddbc, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL)
Destroying MS object, TLLI = 0xffeeddbc
+Creating MS object, TLLI = 0xffeeddbb
+Attaching TBF to MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL)
+Attaching TBF to MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL)
+Detaching TBF from MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=NULL)
+Detaching TBF from MS object, TLLI = 0xffeeddbb, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL)
+Timeout for MS object, TLLI = 0xffeeddbb
+Destroying MS object, TLLI = 0xffeeddbb
diff --git a/tests/ms/MsTest.ok b/tests/ms/MsTest.ok
index 004b36d4..c49e840a 100644
--- a/tests/ms/MsTest.ok
+++ b/tests/ms/MsTest.ok
@@ -12,3 +12,7 @@
=== end test_ms_change_tlli ===
=== start test_ms_storage ===
=== end test_ms_storage ===
+=== start test_ms_timeout ===
+ ms_active() was called
+ ms_idle() was called
+=== end test_ms_timeout ===