diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/gprs_ms.cpp | 182 | ||||
-rw-r--r-- | src/gprs_ms.h | 79 |
3 files changed, 263 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 210774c1..8a422f64 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -37,6 +37,7 @@ libgprs_la_SOURCES = \ gprs_rlcmac_sched.cpp \ gprs_rlcmac_meas.cpp \ gprs_rlcmac_ts_alloc.cpp \ + gprs_ms.cpp \ gsm_timer.cpp \ bitvector.cpp \ pcu_l1_if.cpp \ @@ -77,6 +78,7 @@ noinst_HEADERS = \ gsm_rlcmac.h \ gprs_bssgp_pcu.h \ gprs_rlcmac.h \ + gprs_ms.h \ pcuif_proto.h \ pcu_l1_if.h \ gsm_timer.h \ diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp new file mode 100644 index 00000000..db29d206 --- /dev/null +++ b/src/gprs_ms.cpp @@ -0,0 +1,182 @@ +/* gprs_ms.cpp + * + * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH + * Author: Jacob Erlbeck <jerlbeck@sysmocom.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + + +#include "gprs_ms.h" + +#include "tbf.h" +#include "gprs_debug.h" + +extern "C" { + #include <osmocom/core/talloc.h> + #include <osmocom/core/utils.h> +} + +extern void *tall_pcu_ctx; + +struct GprsMsDefaultCallback: public GprsMs::Callback { + virtual void ms_idle(class GprsMs *ms) { + delete ms; + } + virtual void ms_active(class GprsMs *) {} +}; + +static GprsMsDefaultCallback gprs_default_cb; + + +GprsMs::Guard::Guard(GprsMs *ms) : m_ms(ms) +{ + if (m_ms) + m_ms->ref(); +} + +GprsMs::Guard::~Guard() +{ + if (m_ms) + m_ms->unref(); +} + +GprsMs::GprsMs(uint32_t tlli) : + m_cb(&gprs_default_cb), + m_ul_tbf(NULL), + m_dl_tbf(NULL), + m_tlli(tlli), + m_is_idle(true), + m_ref(0) +{ + LOGP(DRLCMAC, LOGL_INFO, "Creating MS object, TLLI = 0x%08x\n", tlli); +} + +GprsMs::~GprsMs() +{ + LOGP(DRLCMAC, LOGL_INFO, "Destroying MS object, TLLI = 0x%08x\n", tlli()); +} + +void* GprsMs::operator new(size_t size) +{ + static void *tall_ms_ctx = NULL; + if (!tall_ms_ctx) + tall_ms_ctx = talloc_named_const(tall_pcu_ctx, 0, __PRETTY_FUNCTION__); + + return talloc_size(tall_ms_ctx, size); +} + +void GprsMs::operator delete(void* p) +{ + talloc_free(p); +} + +void GprsMs::ref() +{ + m_ref += 1; +} + +void GprsMs::unref() +{ + OSMO_ASSERT(m_ref >= 0); + m_ref -= 1; + if (m_ref == 0) + update_status(); +} + +void GprsMs::attach_tbf(struct gprs_rlcmac_tbf *tbf) +{ + if (tbf->direction == GPRS_RLCMAC_DL_TBF) + attach_dl_tbf(static_cast<gprs_rlcmac_dl_tbf *>(tbf)); + else + attach_ul_tbf(static_cast<gprs_rlcmac_ul_tbf *>(tbf)); +} + +void GprsMs::attach_ul_tbf(struct gprs_rlcmac_ul_tbf *tbf) +{ + if (m_ul_tbf == tbf) + return; + + LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n", + tlli(), tbf->name()); + + Guard guard(this); + + if (m_ul_tbf) + detach_tbf(m_ul_tbf); + + m_ul_tbf = tbf; +} + +void GprsMs::attach_dl_tbf(struct gprs_rlcmac_dl_tbf *tbf) +{ + if (m_dl_tbf == tbf) + return; + + LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n", + tlli(), tbf->name()); + + Guard guard(this); + + if (m_dl_tbf) + detach_tbf(m_dl_tbf); + + m_dl_tbf = tbf; +} + +void GprsMs::detach_tbf(gprs_rlcmac_tbf *tbf) +{ + if (m_ul_tbf && tbf == static_cast<gprs_rlcmac_tbf *>(m_ul_tbf)) + m_ul_tbf = NULL; + else if (m_dl_tbf && tbf == static_cast<gprs_rlcmac_tbf *>(m_dl_tbf)) + m_dl_tbf = NULL; + else + return; + + LOGP(DRLCMAC, LOGL_INFO, "Detaching TBF from MS object, TLLI = 0x%08x, TBF = %s\n", + tlli(), tbf->name()); + + update_status(); +} + +void GprsMs::update_status() +{ + if (m_ref > 0) + return; + + if (is_idle() && !m_is_idle) { + m_is_idle = true; + m_cb->ms_idle(this); + /* this can be deleted by now, do not access it */ + return; + } + + if (!is_idle() && m_is_idle) { + m_is_idle = false; + m_cb->ms_active(this); + } +} + +void GprsMs::set_tlli(uint32_t tlli) +{ + if (tlli == m_tlli) + return; + + LOGP(DRLCMAC, LOGL_INFO, + "Modifying MS object, TLLI: 0x%08x -> 0x%08x\n", + m_tlli, tlli); + + m_tlli = tlli; +} diff --git a/src/gprs_ms.h b/src/gprs_ms.h new file mode 100644 index 00000000..a59fc5be --- /dev/null +++ b/src/gprs_ms.h @@ -0,0 +1,79 @@ +/* gprs_ms.h + * + * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH + * Author: Jacob Erlbeck <jerlbeck@sysmocom.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#pragma once + +struct gprs_rlcmac_tbf; +struct gprs_rlcmac_dl_tbf; +struct gprs_rlcmac_ul_tbf; + +#include <stdint.h> +#include <stddef.h> + +class GprsMs { +public: + struct Callback { + virtual void ms_idle(class GprsMs *) = 0; + virtual void ms_active(class GprsMs *) = 0; + }; + + class Guard { + public: + Guard(GprsMs *ms); + ~Guard(); + + private: + GprsMs * const m_ms; + }; + + GprsMs(uint32_t tlli); + ~GprsMs(); + + void set_callback(Callback *cb) {m_cb = cb;} + + gprs_rlcmac_ul_tbf *ul_tbf() const {return m_ul_tbf;} + gprs_rlcmac_dl_tbf *dl_tbf() const {return m_dl_tbf;} + uint32_t tlli() const {return m_tlli;} + void set_tlli(uint32_t tlli); + + 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); + + void detach_tbf(gprs_rlcmac_tbf *tbf); + + bool is_idle() const {return !m_ul_tbf && !m_dl_tbf && !m_ref;} + + void* operator new(size_t num); + void operator delete(void* p); + +protected: + void update_status(); + void ref(); + void unref(); + +private: + Callback * m_cb; + gprs_rlcmac_ul_tbf *m_ul_tbf; + gprs_rlcmac_dl_tbf *m_dl_tbf; + uint32_t m_tlli; + bool m_is_idle; + int m_ref; +}; |