osmo-pcu/src/gprs_ms.cpp

183 lines
3.6 KiB
C++

/* 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;
}