aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/gprs_ms.cpp182
-rw-r--r--src/gprs_ms.h79
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;
+};