diff options
-rw-r--r-- | src/gprs_ms.cpp | 57 | ||||
-rw-r--r-- | src/gprs_ms.h | 21 | ||||
-rw-r--r-- | tests/ms/MsTest.cpp | 70 | ||||
-rw-r--r-- | tests/ms/MsTest.err | 7 | ||||
-rw-r--r-- | tests/ms/MsTest.ok | 4 |
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 === |