aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-05-28 15:43:53 +0200
committerJacob Erlbeck <jerlbeck@sysmocom.de>2015-05-28 16:38:16 +0200
commitd9e102472a97c767cba1bd5687db30028436d623 (patch)
tree63e8d6c08fddf98cb0c2391c0f0ed1068c54dcd5 /src
parent1db67e0a35a479ef20b871c459ea3f3e0155b620 (diff)
ms: Add timer
Currently the MS object is immediately idle when all TBFs are detached and if no guard is being used. Since the plan is to use the MS objects to pass information from one TBF to the next one even across the gap of some seconds of inactivity, a mechanism is needed to keep the MS objects around for some time. This commit extends the GprsMs class by a timer that keeps the MS objects in non-idle state for some time after all TBFs have been detached. The set_timeout method must be used with a non-zero value to activate this feature. Sponsored-by: On-Waves ehf
Diffstat (limited to 'src')
-rw-r--r--src/gprs_ms.cpp57
-rw-r--r--src/gprs_ms.h21
2 files changed, 72 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;
+}