blob: d9d74f4dc9ca8203571e1931a88aff4841addbb7 [file] [log] [blame]
Jacob Erlbecke04e0b02015-05-06 18:30:48 +02001/* gprs_ms.cpp
2 *
3 * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
4 * Author: Jacob Erlbeck <jerlbeck@sysmocom.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20
21
22#include "gprs_ms.h"
23
24#include "tbf.h"
25#include "gprs_debug.h"
26
27extern "C" {
28 #include <osmocom/core/talloc.h>
29 #include <osmocom/core/utils.h>
30}
31
32extern void *tall_pcu_ctx;
33
34struct GprsMsDefaultCallback: public GprsMs::Callback {
35 virtual void ms_idle(class GprsMs *ms) {
36 delete ms;
37 }
38 virtual void ms_active(class GprsMs *) {}
39};
40
41static GprsMsDefaultCallback gprs_default_cb;
42
43
44GprsMs::Guard::Guard(GprsMs *ms) : m_ms(ms)
45{
46 if (m_ms)
47 m_ms->ref();
48}
49
50GprsMs::Guard::~Guard()
51{
52 if (m_ms)
53 m_ms->unref();
54}
55
56GprsMs::GprsMs(uint32_t tlli) :
57 m_cb(&gprs_default_cb),
58 m_ul_tbf(NULL),
59 m_dl_tbf(NULL),
60 m_tlli(tlli),
61 m_is_idle(true),
62 m_ref(0)
63{
64 LOGP(DRLCMAC, LOGL_INFO, "Creating MS object, TLLI = 0x%08x\n", tlli);
65}
66
67GprsMs::~GprsMs()
68{
69 LOGP(DRLCMAC, LOGL_INFO, "Destroying MS object, TLLI = 0x%08x\n", tlli());
Jacob Erlbeckfecece02015-05-08 12:13:08 +020070
71 if (m_ul_tbf) {
72 m_ul_tbf->set_ms(NULL);
73 m_ul_tbf = NULL;
74 }
75
76 if (m_dl_tbf) {
77 m_dl_tbf->set_ms(NULL);
78 m_dl_tbf = NULL;
79 }
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020080}
81
82void* GprsMs::operator new(size_t size)
83{
84 static void *tall_ms_ctx = NULL;
85 if (!tall_ms_ctx)
86 tall_ms_ctx = talloc_named_const(tall_pcu_ctx, 0, __PRETTY_FUNCTION__);
87
88 return talloc_size(tall_ms_ctx, size);
89}
90
91void GprsMs::operator delete(void* p)
92{
93 talloc_free(p);
94}
95
96void GprsMs::ref()
97{
98 m_ref += 1;
99}
100
101void GprsMs::unref()
102{
103 OSMO_ASSERT(m_ref >= 0);
104 m_ref -= 1;
105 if (m_ref == 0)
106 update_status();
107}
108
109void GprsMs::attach_tbf(struct gprs_rlcmac_tbf *tbf)
110{
111 if (tbf->direction == GPRS_RLCMAC_DL_TBF)
112 attach_dl_tbf(static_cast<gprs_rlcmac_dl_tbf *>(tbf));
113 else
114 attach_ul_tbf(static_cast<gprs_rlcmac_ul_tbf *>(tbf));
115}
116
117void GprsMs::attach_ul_tbf(struct gprs_rlcmac_ul_tbf *tbf)
118{
119 if (m_ul_tbf == tbf)
120 return;
121
122 LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n",
123 tlli(), tbf->name());
124
125 Guard guard(this);
126
127 if (m_ul_tbf)
128 detach_tbf(m_ul_tbf);
129
130 m_ul_tbf = tbf;
131}
132
133void GprsMs::attach_dl_tbf(struct gprs_rlcmac_dl_tbf *tbf)
134{
135 if (m_dl_tbf == tbf)
136 return;
137
138 LOGP(DRLCMAC, LOGL_INFO, "Attaching TBF to MS object, TLLI = 0x%08x, TBF = %s\n",
139 tlli(), tbf->name());
140
141 Guard guard(this);
142
143 if (m_dl_tbf)
144 detach_tbf(m_dl_tbf);
145
146 m_dl_tbf = tbf;
147}
148
149void GprsMs::detach_tbf(gprs_rlcmac_tbf *tbf)
150{
151 if (m_ul_tbf && tbf == static_cast<gprs_rlcmac_tbf *>(m_ul_tbf))
152 m_ul_tbf = NULL;
153 else if (m_dl_tbf && tbf == static_cast<gprs_rlcmac_tbf *>(m_dl_tbf))
154 m_dl_tbf = NULL;
155 else
156 return;
157
158 LOGP(DRLCMAC, LOGL_INFO, "Detaching TBF from MS object, TLLI = 0x%08x, TBF = %s\n",
159 tlli(), tbf->name());
160
Jacob Erlbeckfecece02015-05-08 12:13:08 +0200161 if (tbf->ms() == this)
162 tbf->set_ms(NULL);
163
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200164 update_status();
165}
166
167void GprsMs::update_status()
168{
169 if (m_ref > 0)
170 return;
171
172 if (is_idle() && !m_is_idle) {
173 m_is_idle = true;
174 m_cb->ms_idle(this);
175 /* this can be deleted by now, do not access it */
176 return;
177 }
178
179 if (!is_idle() && m_is_idle) {
180 m_is_idle = false;
181 m_cb->ms_active(this);
182 }
183}
184
185void GprsMs::set_tlli(uint32_t tlli)
186{
187 if (tlli == m_tlli)
188 return;
189
190 LOGP(DRLCMAC, LOGL_INFO,
191 "Modifying MS object, TLLI: 0x%08x -> 0x%08x\n",
192 m_tlli, tlli);
193
194 m_tlli = tlli;
195}