Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
/* gprs_ms.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 2015-2020 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 "bts.h"
|
|
|
|
#include "tbf.h"
|
|
|
|
#include "tbf_ul.h"
|
|
|
|
#include "gprs_debug.h"
|
|
|
|
#include "gprs_codel.h"
|
|
|
|
#include "pcu_utils.h"
|
Introduce NACC support
A new nacc_fsm is introduced per MS object, with its partner priv
structure struct nacc_fsm_ctx, which exists and is available in the MS
object only during the duration of the NACC procedure.
The NACC context is created on an MS whenever a Pkt Cell Change
Notification is received on Uplink RLCMAC, which asks for neighbor
information of a given ARFCN+BSIC.
First, the target ARFCN+BSIC needs to be translated into a CGI-PS
(RAC+CI) address. That's done by asking the BSC through the Neighbour
Resolution Service available in osmo-bsc using the CTRL interface.
Once the CGI-PS of the target cell is known, PCU starts a RIM RAN-INFO
request against the SGSN (which will route the request as needed), and
wait for a response containing the SI bits from the target cell.
After the SI are received, the scheduler is instructed to eventually
poll a TBF for the MS originating the CCN, so that we can send the SI
encapsulated into multiple Packet Neighbor Cell Data messages on the
downlink.
One all the SI bits are sent, the scheduler is instructed to send a
Packet Cell Change Continue message.
Once the message above has been sent, the FSM autodestroys itself.
Caches are also introduced in this patch which allows for re-using
recently known translations ARFCN+BSIC -> CGI-PS and CGI-PS -> SI_INFO
respectively.
Change-Id: Id35f40d05f3e081f32fddbf1fa34cb338db452ca
2021-01-21 17:46:13 +00:00
|
|
|
#include "nacc_fsm.h"
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
|
|
|
|
#include <osmocom/core/talloc.h>
|
|
|
|
#include <osmocom/core/utils.h>
|
|
|
|
#include <osmocom/core/timer.h>
|
|
|
|
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
|
|
|
#include <osmocom/gsm/gsm48.h>
|
|
|
|
#include <osmocom/core/logging.h>
|
2021-01-11 16:32:18 +00:00
|
|
|
#include <osmocom/core/stats.h>
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
#include "coding_scheme.h"
|
|
|
|
|
|
|
|
#define GPRS_CODEL_SLOW_INTERVAL_MS 4000
|
|
|
|
|
|
|
|
extern void *tall_pcu_ctx;
|
2021-01-11 16:32:18 +00:00
|
|
|
static unsigned int next_ms_ctr_group_id;
|
|
|
|
|
|
|
|
static const struct rate_ctr_desc ms_ctr_description[] = {
|
|
|
|
[MS_CTR_DL_CTRL_MSG_SCHED] = { "ms:dl_ctrl_msg_sched", "Amount of DL CTRL messages scheduled" },
|
|
|
|
};
|
|
|
|
|
2021-01-12 19:57:56 +00:00
|
|
|
static const struct rate_ctr_group_desc ms_ctrg_desc = {
|
2021-01-11 16:32:18 +00:00
|
|
|
.group_name_prefix = "pcu:ms",
|
|
|
|
.group_description = "MS Statistics",
|
|
|
|
.class_id = OSMO_STATS_CLASS_SUBSCRIBER,
|
|
|
|
.num_ctr = ARRAY_SIZE(ms_ctr_description),
|
|
|
|
.ctr_desc = ms_ctr_description,
|
|
|
|
};
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
static int64_t now_msec()
|
|
|
|
{
|
|
|
|
struct timespec ts;
|
|
|
|
osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
|
|
|
|
|
|
return (int64_t)(ts.tv_sec) * 1000 + ts.tv_nsec / 1000000;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gprs_default_cb_ms_idle(struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
talloc_free(ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
void gprs_default_cb_ms_active(struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
/* do nothing */
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct gpr_ms_callback gprs_default_cb = {
|
|
|
|
.ms_idle = gprs_default_cb_ms_idle,
|
|
|
|
.ms_active = gprs_default_cb_ms_active,
|
|
|
|
};
|
|
|
|
|
2021-03-03 16:30:50 +00:00
|
|
|
static void ms_release_timer_cb(void *data)
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
{
|
|
|
|
struct GprsMs *ms = (struct GprsMs *) data;
|
2021-03-03 16:30:50 +00:00
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_INFO, "Release timer expired\n");
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
if (ms->timer.data) {
|
|
|
|
ms->timer.data = NULL;
|
|
|
|
ms_unref(ms);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ms_talloc_destructor(struct GprsMs *ms);
|
2021-01-14 15:48:38 +00:00
|
|
|
struct GprsMs *ms_alloc(struct gprs_rlcmac_bts *bts, uint32_t tlli)
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
{
|
|
|
|
struct GprsMs *ms = talloc_zero(tall_pcu_ctx, struct GprsMs);
|
|
|
|
|
|
|
|
talloc_set_destructor(ms, ms_talloc_destructor);
|
|
|
|
|
|
|
|
ms->bts = bts;
|
|
|
|
ms->cb = gprs_default_cb;
|
|
|
|
ms->tlli = tlli;
|
|
|
|
ms->new_ul_tlli = GSM_RESERVED_TMSI;
|
|
|
|
ms->new_dl_tlli = GSM_RESERVED_TMSI;
|
|
|
|
ms->ta = GSM48_TA_INVALID;
|
|
|
|
ms->current_cs_ul = UNKNOWN;
|
|
|
|
ms->current_cs_dl = UNKNOWN;
|
|
|
|
ms->is_idle = true;
|
|
|
|
INIT_LLIST_HEAD(&ms->list);
|
|
|
|
INIT_LLIST_HEAD(&ms->old_tbfs);
|
|
|
|
|
|
|
|
int codel_interval = LLC_CODEL_USE_DEFAULT;
|
|
|
|
|
|
|
|
LOGP(DRLCMAC, LOGL_INFO, "Creating MS object, TLLI = 0x%08x\n", tlli);
|
|
|
|
|
|
|
|
ms->imsi[0] = '\0';
|
|
|
|
memset(&ms->timer, 0, sizeof(ms->timer));
|
2021-03-03 16:30:50 +00:00
|
|
|
ms->timer.cb = ms_release_timer_cb;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
llc_queue_init(&ms->llc_queue);
|
|
|
|
|
|
|
|
ms_set_mode(ms, GPRS);
|
|
|
|
|
|
|
|
if (ms->bts)
|
2021-01-14 13:45:14 +00:00
|
|
|
codel_interval = the_pcu->vty.llc_codel_interval_msec;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
if (codel_interval) {
|
|
|
|
if (codel_interval == LLC_CODEL_USE_DEFAULT)
|
|
|
|
codel_interval = GPRS_CODEL_SLOW_INTERVAL_MS;
|
|
|
|
ms->codel_state = talloc(ms, struct gprs_codel);
|
|
|
|
gprs_codel_init(ms->codel_state);
|
|
|
|
gprs_codel_set_interval(ms->codel_state, codel_interval);
|
|
|
|
}
|
|
|
|
ms->last_cs_not_low = now_msec();
|
|
|
|
ms->app_info_pending = false;
|
2021-01-11 16:32:18 +00:00
|
|
|
|
|
|
|
ms->ctrs = rate_ctr_group_alloc(ms, &ms_ctrg_desc, next_ms_ctr_group_id++);
|
|
|
|
if (!ms->ctrs)
|
|
|
|
goto free_ret;
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
return ms;
|
2021-01-11 16:32:18 +00:00
|
|
|
free_ret:
|
|
|
|
talloc_free(ms);
|
|
|
|
return NULL;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int ms_talloc_destructor(struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
struct llist_item *pos, *tmp;
|
|
|
|
|
2021-03-03 19:37:38 +00:00
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_INFO, "Destroying MS object\n");
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
ms_set_reserved_slots(ms, NULL, 0, 0);
|
|
|
|
|
|
|
|
if (osmo_timer_pending(&ms->timer))
|
|
|
|
osmo_timer_del(&ms->timer);
|
|
|
|
|
|
|
|
if (ms->ul_tbf) {
|
|
|
|
tbf_set_ms((struct gprs_rlcmac_tbf *)ms->ul_tbf, NULL);
|
|
|
|
ms->ul_tbf = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ms->dl_tbf) {
|
|
|
|
tbf_set_ms((struct gprs_rlcmac_tbf *)ms->dl_tbf, NULL);
|
|
|
|
ms->dl_tbf = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
llist_for_each_entry_safe(pos, tmp, &ms->old_tbfs, list) {
|
|
|
|
struct gprs_rlcmac_tbf *tbf = (struct gprs_rlcmac_tbf *)pos->entry;
|
|
|
|
tbf_set_ms(tbf, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
llc_queue_clear(&ms->llc_queue, ms->bts);
|
2021-01-11 16:32:18 +00:00
|
|
|
|
|
|
|
if (ms->ctrs)
|
|
|
|
rate_ctr_group_free(ms->ctrs);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ms_set_callback(struct GprsMs *ms, struct gpr_ms_callback *cb)
|
|
|
|
{
|
|
|
|
if (cb)
|
|
|
|
ms->cb = *cb;
|
|
|
|
else
|
|
|
|
ms->cb = gprs_default_cb;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ms_update_status(struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
if (ms->ref > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (ms_is_idle(ms) && !ms->is_idle) {
|
|
|
|
ms->is_idle = true;
|
|
|
|
ms->cb.ms_idle(ms);
|
|
|
|
/* this can be deleted by now, do not access it */
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ms_is_idle(ms) && ms->is_idle) {
|
|
|
|
ms->is_idle = false;
|
|
|
|
ms->cb.ms_active(ms);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct GprsMs *ms_ref(struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
ms->ref += 1;
|
|
|
|
return ms;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_unref(struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
OSMO_ASSERT(ms->ref >= 0);
|
|
|
|
ms->ref -= 1;
|
|
|
|
if (ms->ref == 0)
|
|
|
|
ms_update_status(ms);
|
|
|
|
}
|
|
|
|
|
2021-03-03 16:30:50 +00:00
|
|
|
static void ms_release_timer_start(struct GprsMs *ms)
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
{
|
|
|
|
if (ms->delay == 0)
|
|
|
|
return;
|
|
|
|
|
2021-03-03 16:30:50 +00:00
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_DEBUG, "Schedule MS release in %u secs\n", ms->delay);
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
if (!ms->timer.data)
|
|
|
|
ms->timer.data = ms_ref(ms);
|
|
|
|
|
|
|
|
osmo_timer_schedule(&ms->timer, ms->delay, 0);
|
|
|
|
}
|
|
|
|
|
2021-03-03 16:30:50 +00:00
|
|
|
static void ms_release_timer_stop(struct GprsMs *ms)
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
{
|
|
|
|
if (!ms->timer.data)
|
|
|
|
return;
|
|
|
|
|
2021-03-03 16:30:50 +00:00
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_DEBUG, "Cancel scheduled MS release\n");
|
|
|
|
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
osmo_timer_del(&ms->timer);
|
|
|
|
ms->timer.data = NULL;
|
|
|
|
ms_unref(ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_set_mode(struct GprsMs *ms, enum mcs_kind mode)
|
|
|
|
{
|
|
|
|
ms->mode = mode;
|
|
|
|
|
|
|
|
switch (ms->mode) {
|
|
|
|
case GPRS:
|
|
|
|
if (!mcs_is_gprs(ms->current_cs_ul)) {
|
|
|
|
ms->current_cs_ul = mcs_get_gprs_by_num(
|
2021-01-14 15:48:38 +00:00
|
|
|
ms->bts->initial_cs_ul);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
if (!mcs_is_valid(ms->current_cs_ul))
|
|
|
|
ms->current_cs_ul = CS1;
|
|
|
|
}
|
|
|
|
if (!mcs_is_gprs(ms->current_cs_dl)) {
|
|
|
|
ms->current_cs_dl = mcs_get_gprs_by_num(
|
2021-01-14 15:48:38 +00:00
|
|
|
ms->bts->initial_cs_dl);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
if (!mcs_is_valid(ms->current_cs_dl))
|
|
|
|
ms->current_cs_dl = CS1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case EGPRS_GMSK:
|
2021-01-25 14:08:35 +00:00
|
|
|
if (!mcs_is_edge_gmsk(ms->current_cs_ul)) {
|
|
|
|
ms->current_cs_ul = mcs_get_egprs_by_num(
|
|
|
|
ms->bts->initial_mcs_ul);
|
|
|
|
if (!mcs_is_valid(ms->current_cs_ul))
|
|
|
|
ms->current_cs_ul = MCS1;
|
|
|
|
}
|
|
|
|
if (!mcs_is_edge_gmsk(ms->current_cs_dl)) {
|
|
|
|
ms->current_cs_dl = mcs_get_egprs_by_num(
|
|
|
|
ms->bts->initial_mcs_dl);
|
|
|
|
if (!mcs_is_valid(ms->current_cs_dl))
|
|
|
|
ms->current_cs_dl = MCS1;
|
|
|
|
}
|
|
|
|
break;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
case EGPRS:
|
|
|
|
if (!mcs_is_edge(ms->current_cs_ul)) {
|
|
|
|
ms->current_cs_ul = mcs_get_egprs_by_num(
|
2021-01-14 15:48:38 +00:00
|
|
|
ms->bts->initial_mcs_ul);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
if (!mcs_is_valid(ms->current_cs_ul))
|
|
|
|
ms->current_cs_ul = MCS1;
|
|
|
|
}
|
|
|
|
if (!mcs_is_edge(ms->current_cs_dl)) {
|
|
|
|
ms->current_cs_dl = mcs_get_egprs_by_num(
|
2021-01-14 15:48:38 +00:00
|
|
|
ms->bts->initial_mcs_dl);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
if (!mcs_is_valid(ms->current_cs_dl))
|
|
|
|
ms->current_cs_dl = MCS1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ms_attach_ul_tbf(struct GprsMs *ms, struct gprs_rlcmac_ul_tbf *tbf)
|
|
|
|
{
|
|
|
|
if (ms->ul_tbf == tbf)
|
|
|
|
return;
|
|
|
|
|
2021-03-03 19:37:38 +00:00
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_INFO, "Attaching UL TBF: %s\n", tbf_name((struct gprs_rlcmac_tbf *)tbf));
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
ms_ref(ms);
|
|
|
|
|
|
|
|
if (ms->ul_tbf)
|
|
|
|
llist_add_tail(tbf_ms_list((struct gprs_rlcmac_tbf *)ms->ul_tbf), &ms->old_tbfs);
|
|
|
|
|
|
|
|
ms->ul_tbf = tbf;
|
|
|
|
|
|
|
|
if (tbf)
|
2021-03-03 16:30:50 +00:00
|
|
|
ms_release_timer_stop(ms);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
ms_unref(ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ms_attach_dl_tbf(struct GprsMs *ms, struct gprs_rlcmac_dl_tbf *tbf)
|
|
|
|
{
|
|
|
|
if (ms->dl_tbf == tbf)
|
|
|
|
return;
|
|
|
|
|
2021-03-03 19:37:38 +00:00
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_INFO, "Attaching DL TBF: %s\n", tbf_name((struct gprs_rlcmac_tbf *)tbf));
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
ms_ref(ms);
|
|
|
|
|
|
|
|
if (ms->dl_tbf)
|
|
|
|
llist_add_tail(tbf_ms_list((struct gprs_rlcmac_tbf *)ms->dl_tbf), &ms->old_tbfs);
|
|
|
|
|
|
|
|
ms->dl_tbf = tbf;
|
|
|
|
|
|
|
|
if (tbf)
|
2021-03-03 16:30:50 +00:00
|
|
|
ms_release_timer_stop(ms);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
ms_unref(ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_attach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf)
|
|
|
|
{
|
2021-08-23 14:58:04 +00:00
|
|
|
if (tbf_direction(tbf) == GPRS_RLCMAC_DL_TBF)
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_attach_dl_tbf(ms, as_dl_tbf(tbf));
|
2021-08-23 14:58:04 +00:00
|
|
|
else
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
ms_attach_ul_tbf(ms, as_ul_tbf(tbf));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_detach_tbf(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf)
|
|
|
|
{
|
|
|
|
if (tbf == (struct gprs_rlcmac_tbf *)(ms->ul_tbf)) {
|
|
|
|
ms->ul_tbf = NULL;
|
|
|
|
} else if (tbf == (struct gprs_rlcmac_tbf *)(ms->dl_tbf)) {
|
|
|
|
ms->dl_tbf = NULL;
|
|
|
|
} else {
|
|
|
|
bool found = false;
|
|
|
|
|
|
|
|
struct llist_item *pos, *tmp;
|
|
|
|
llist_for_each_entry_safe(pos, tmp, &ms->old_tbfs, list) {
|
|
|
|
struct gprs_rlcmac_tbf *tmp_tbf = (struct gprs_rlcmac_tbf *)pos->entry;
|
|
|
|
if (tmp_tbf == tbf) {
|
|
|
|
llist_del(&pos->list);
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Protect against recursive calls via set_ms() */
|
|
|
|
if (!found)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-03 19:37:38 +00:00
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_INFO, "Detaching TBF: %s\n",
|
|
|
|
tbf_name(tbf));
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
if (tbf_ms(tbf) == ms)
|
|
|
|
tbf_set_ms(tbf, NULL);
|
|
|
|
|
|
|
|
if (!ms->dl_tbf && !ms->ul_tbf) {
|
|
|
|
ms_set_reserved_slots(ms, NULL, 0, 0);
|
|
|
|
|
|
|
|
if (ms_tlli(ms) != 0)
|
2021-03-03 16:30:50 +00:00
|
|
|
ms_release_timer_start(ms);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ms_update_status(ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_reset(struct GprsMs *ms)
|
|
|
|
{
|
2021-03-03 19:37:38 +00:00
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_INFO, "Clearing MS object\n");
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
2021-03-03 16:30:50 +00:00
|
|
|
ms_release_timer_stop(ms);
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
ms->tlli = GSM_RESERVED_TMSI;
|
|
|
|
ms->new_dl_tlli = ms->tlli;
|
|
|
|
ms->new_ul_tlli = ms->tlli;
|
|
|
|
ms->imsi[0] = '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ms_merge_old_ms(struct GprsMs *ms, struct GprsMs *old_ms)
|
|
|
|
{
|
|
|
|
OSMO_ASSERT(old_ms != ms);
|
|
|
|
|
|
|
|
if (strlen(ms_imsi(ms)) == 0 && strlen(ms_imsi(old_ms)) != 0)
|
|
|
|
osmo_strlcpy(ms->imsi, ms_imsi(old_ms), sizeof(ms->imsi));
|
|
|
|
|
|
|
|
if (!ms_ms_class(ms) && ms_ms_class(old_ms))
|
|
|
|
ms_set_ms_class(ms, ms_ms_class(old_ms));
|
|
|
|
|
|
|
|
if (!ms_egprs_ms_class(ms) && ms_egprs_ms_class(old_ms))
|
|
|
|
ms_set_egprs_ms_class(ms, ms_egprs_ms_class(old_ms));
|
|
|
|
|
|
|
|
llc_queue_move_and_merge(&ms->llc_queue, &old_ms->llc_queue);
|
|
|
|
|
|
|
|
ms_reset(old_ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_merge_and_clear_ms(struct GprsMs *ms, struct GprsMs *old_ms)
|
|
|
|
{
|
|
|
|
OSMO_ASSERT(old_ms != ms);
|
|
|
|
|
|
|
|
ms_ref(old_ms);
|
|
|
|
|
|
|
|
/* Clean up the old MS object */
|
|
|
|
/* TODO: Use timer? */
|
|
|
|
if (ms_ul_tbf(old_ms) && !tbf_timers_pending((struct gprs_rlcmac_tbf *)ms_ul_tbf(old_ms), T_MAX))
|
|
|
|
tbf_free((struct gprs_rlcmac_tbf *)ms_ul_tbf(old_ms));
|
|
|
|
if (ms_dl_tbf(old_ms) && !tbf_timers_pending((struct gprs_rlcmac_tbf *)ms_dl_tbf(old_ms), T_MAX))
|
|
|
|
tbf_free((struct gprs_rlcmac_tbf *)ms_dl_tbf(old_ms));
|
|
|
|
|
|
|
|
ms_merge_old_ms(ms, old_ms);
|
|
|
|
|
|
|
|
ms_unref(old_ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_set_tlli(struct GprsMs *ms, uint32_t tlli)
|
|
|
|
{
|
|
|
|
if (tlli == ms->tlli || tlli == ms->new_ul_tlli)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (tlli != ms->new_dl_tlli) {
|
|
|
|
LOGP(DRLCMAC, LOGL_INFO,
|
|
|
|
"Modifying MS object, UL TLLI: 0x%08x -> 0x%08x, "
|
|
|
|
"not yet confirmed\n",
|
|
|
|
ms_tlli(ms), tlli);
|
|
|
|
ms->new_ul_tlli = tlli;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOGP(DRLCMAC, LOGL_INFO,
|
|
|
|
"Modifying MS object, TLLI: 0x%08x -> 0x%08x, "
|
|
|
|
"already confirmed partly\n",
|
|
|
|
ms->tlli, tlli);
|
|
|
|
|
|
|
|
ms->tlli = tlli;
|
|
|
|
ms->new_dl_tlli = GSM_RESERVED_TMSI;
|
|
|
|
ms->new_ul_tlli = GSM_RESERVED_TMSI;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ms_confirm_tlli(struct GprsMs *ms, uint32_t tlli)
|
|
|
|
{
|
|
|
|
if (tlli == ms->tlli || tlli == ms->new_dl_tlli)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (tlli != ms->new_ul_tlli) {
|
|
|
|
/* The MS has not sent a message with the new TLLI, which may
|
|
|
|
* happen according to the spec [TODO: add reference]. */
|
|
|
|
|
|
|
|
LOGP(DRLCMAC, LOGL_INFO,
|
|
|
|
"The MS object cannot fully confirm an unexpected TLLI: 0x%08x, "
|
|
|
|
"partly confirmed\n", tlli);
|
|
|
|
/* Use the network's idea of TLLI as candidate, this does not
|
|
|
|
* change the result value of tlli() */
|
|
|
|
ms->new_dl_tlli = tlli;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOGP(DRLCMAC, LOGL_INFO,
|
|
|
|
"Modifying MS object, TLLI: 0x%08x confirmed\n", tlli);
|
|
|
|
|
|
|
|
ms->tlli = tlli;
|
|
|
|
ms->new_dl_tlli = GSM_RESERVED_TMSI;
|
|
|
|
ms->new_ul_tlli = GSM_RESERVED_TMSI;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_set_imsi(struct GprsMs *ms, const char *imsi)
|
|
|
|
{
|
|
|
|
if (!imsi) {
|
|
|
|
LOGP(DRLCMAC, LOGL_ERROR, "Expected IMSI!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (imsi[0] && strlen(imsi) < 3) {
|
|
|
|
LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI '%s'!\n",
|
|
|
|
imsi);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strcmp(imsi, ms->imsi) == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
LOGP(DRLCMAC, LOGL_INFO,
|
|
|
|
"Modifying MS object, TLLI = 0x%08x, IMSI '%s' -> '%s'\n",
|
|
|
|
ms_tlli(ms), ms->imsi, imsi);
|
|
|
|
|
|
|
|
struct GprsMs *old_ms = bts_ms_by_imsi(ms->bts, imsi);
|
|
|
|
/* Check if we are going to store a different MS object with already
|
|
|
|
existing IMSI. This is probably a bug in code calling this function,
|
|
|
|
since it should take care of this explicitly */
|
|
|
|
if (old_ms) {
|
|
|
|
/* We cannot find ms->ms by IMSI since we know that it has a
|
|
|
|
* different IMSI */
|
|
|
|
OSMO_ASSERT(old_ms != ms);
|
|
|
|
|
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_NOTICE,
|
|
|
|
"IMSI '%s' was already assigned to another "
|
|
|
|
"MS object: TLLI = 0x%08x, that IMSI will be removed\n",
|
|
|
|
imsi, ms_tlli(old_ms));
|
|
|
|
|
|
|
|
ms_merge_and_clear_ms(ms, old_ms);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
osmo_strlcpy(ms->imsi, imsi, sizeof(ms->imsi));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_set_ta(struct GprsMs *ms, uint8_t ta_)
|
|
|
|
{
|
|
|
|
if (ta_ == ms->ta)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (gsm48_ta_is_valid(ta_)) {
|
|
|
|
LOGP(DRLCMAC, LOGL_INFO,
|
|
|
|
"Modifying MS object, TLLI = 0x%08x, TA %d -> %d\n",
|
|
|
|
ms_tlli(ms), ms->ta, ta_);
|
|
|
|
ms->ta = ta_;
|
|
|
|
} else
|
|
|
|
LOGP(DRLCMAC, LOGL_NOTICE,
|
|
|
|
"MS object, TLLI = 0x%08x, invalid TA %d rejected (old "
|
|
|
|
"value %d kept)\n", ms_tlli(ms), ta_, ms->ta);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_set_ms_class(struct GprsMs *ms, uint8_t ms_class_)
|
|
|
|
{
|
|
|
|
if (ms_class_ == ms->ms_class)
|
|
|
|
return;
|
|
|
|
|
|
|
|
LOGP(DRLCMAC, LOGL_INFO,
|
|
|
|
"Modifying MS object, TLLI = 0x%08x, MS class %d -> %d\n",
|
|
|
|
ms_tlli(ms), ms->ms_class, ms_class_);
|
|
|
|
|
|
|
|
ms->ms_class = ms_class_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_set_egprs_ms_class(struct GprsMs *ms, uint8_t ms_class_)
|
|
|
|
{
|
|
|
|
if (ms_class_ == ms->egprs_ms_class)
|
|
|
|
return;
|
|
|
|
|
|
|
|
LOGP(DRLCMAC, LOGL_INFO,
|
|
|
|
"Modifying MS object, TLLI = 0x%08x, EGPRS MS class %d -> %d\n",
|
|
|
|
ms_tlli(ms), ms->egprs_ms_class, ms_class_);
|
|
|
|
|
|
|
|
ms->egprs_ms_class = ms_class_;
|
|
|
|
|
|
|
|
if (!bts_max_mcs_ul(ms->bts) || !bts_max_mcs_dl(ms->bts)) {
|
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_DEBUG,
|
|
|
|
"Avoid enabling EGPRS because use of MCS is disabled: ul=%u dl=%u\n",
|
|
|
|
bts_max_mcs_ul(ms->bts), bts_max_mcs_dl(ms->bts));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mcs_is_edge_gmsk(mcs_get_egprs_by_num(bts_max_mcs_ul(ms->bts))) &&
|
|
|
|
mcs_is_edge_gmsk(mcs_get_egprs_by_num(bts_max_mcs_dl(ms->bts))) &&
|
|
|
|
ms_mode(ms) != EGPRS)
|
|
|
|
{
|
|
|
|
ms_set_mode(ms, EGPRS_GMSK);
|
|
|
|
} else {
|
|
|
|
ms_set_mode(ms, EGPRS);
|
|
|
|
}
|
|
|
|
LOGPMS(ms, DRLCMAC, LOGL_INFO, "Enabled EGPRS, mode %s\n", mode_name(ms_mode(ms)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_update_error_rate(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf, int error_rate)
|
|
|
|
{
|
|
|
|
int64_t now;
|
|
|
|
enum CodingScheme max_cs_dl = ms_max_cs_dl(ms);
|
|
|
|
OSMO_ASSERT(max_cs_dl);
|
|
|
|
|
|
|
|
if (error_rate < 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
now = now_msec();
|
|
|
|
|
|
|
|
/* TODO: Check for TBF direction */
|
|
|
|
/* TODO: Support different CS values for UL and DL */
|
|
|
|
|
|
|
|
ms->nack_rate_dl = error_rate;
|
|
|
|
|
2021-01-14 12:17:01 +00:00
|
|
|
if (error_rate > the_pcu->vty.cs_adj_upper_limit) {
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
if (mcs_chan_code(ms->current_cs_dl) > 0) {
|
|
|
|
mcs_dec_kind(&ms->current_cs_dl, ms_mode(ms));
|
|
|
|
LOGP(DRLCMACDL, LOGL_INFO,
|
|
|
|
"MS (IMSI %s): High error rate %d%%, "
|
|
|
|
"reducing CS level to %s\n",
|
|
|
|
ms_imsi(ms), error_rate, mcs_name(ms->current_cs_dl));
|
|
|
|
ms->last_cs_not_low = now;
|
|
|
|
}
|
2021-01-14 12:17:01 +00:00
|
|
|
} else if (error_rate < the_pcu->vty.cs_adj_lower_limit) {
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
if (ms->current_cs_dl < max_cs_dl) {
|
|
|
|
if (now - ms->last_cs_not_low > 1000) {
|
|
|
|
mcs_inc_kind(&ms->current_cs_dl, ms_mode(ms));
|
|
|
|
|
|
|
|
LOGP(DRLCMACDL, LOGL_INFO,
|
|
|
|
"MS (IMSI %s): Low error rate %d%%, "
|
|
|
|
"increasing DL CS level to %s\n",
|
|
|
|
ms_imsi(ms), error_rate,
|
|
|
|
mcs_name(ms->current_cs_dl));
|
|
|
|
ms->last_cs_not_low = now;
|
|
|
|
} else {
|
|
|
|
LOGP(DRLCMACDL, LOGL_DEBUG,
|
|
|
|
"MS (IMSI %s): Low error rate %d%%, "
|
|
|
|
"ignored (within blocking period)\n",
|
|
|
|
ms_imsi(ms), error_rate);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
LOGP(DRLCMACDL, LOGL_DEBUG,
|
|
|
|
"MS (IMSI %s): Medium error rate %d%%, ignored\n",
|
|
|
|
ms_imsi(ms), error_rate);
|
|
|
|
ms->last_cs_not_low = now;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
enum CodingScheme ms_max_cs_ul(const struct GprsMs *ms)
|
|
|
|
{
|
2021-01-25 14:10:33 +00:00
|
|
|
enum CodingScheme cs;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms->bts != NULL);
|
|
|
|
|
|
|
|
if (mcs_is_gprs(ms->current_cs_ul)) {
|
|
|
|
if (!bts_max_cs_ul(ms->bts)) {
|
|
|
|
return CS4;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mcs_get_gprs_by_num(bts_max_cs_ul(ms->bts));
|
|
|
|
}
|
|
|
|
|
2021-01-25 14:10:33 +00:00
|
|
|
cs = mcs_get_egprs_by_num(bts_max_mcs_ul(ms->bts));
|
|
|
|
if (ms_mode(ms) == EGPRS_GMSK && cs > MCS4)
|
|
|
|
cs = MCS4;
|
|
|
|
return cs;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ms_set_current_cs_dl(struct GprsMs *ms, enum CodingScheme scheme)
|
|
|
|
{
|
|
|
|
ms->current_cs_dl = scheme;
|
|
|
|
}
|
|
|
|
|
|
|
|
enum CodingScheme ms_max_cs_dl(const struct GprsMs *ms)
|
|
|
|
{
|
2021-01-25 14:10:33 +00:00
|
|
|
enum CodingScheme cs;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
OSMO_ASSERT(ms->bts != NULL);
|
|
|
|
|
|
|
|
if (mcs_is_gprs(ms->current_cs_dl)) {
|
|
|
|
if (!bts_max_cs_dl(ms->bts)) {
|
|
|
|
return CS4;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mcs_get_gprs_by_num(bts_max_cs_dl(ms->bts));
|
|
|
|
}
|
|
|
|
|
2021-01-25 14:10:33 +00:00
|
|
|
cs = mcs_get_egprs_by_num(bts_max_mcs_dl(ms->bts));
|
|
|
|
if (ms_mode(ms) == EGPRS_GMSK && cs > MCS4)
|
|
|
|
cs = MCS4;
|
|
|
|
return cs;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void ms_update_cs_ul(struct GprsMs *ms, const struct pcu_l1_meas *meas)
|
|
|
|
{
|
|
|
|
enum CodingScheme max_cs_ul = ms_max_cs_ul(ms);
|
|
|
|
|
|
|
|
int old_link_qual;
|
|
|
|
int low;
|
|
|
|
int high;
|
|
|
|
enum CodingScheme new_cs_ul = ms->current_cs_ul;
|
|
|
|
uint8_t current_cs = mcs_chan_code(ms->current_cs_ul);
|
|
|
|
|
|
|
|
if (!max_cs_ul) {
|
|
|
|
LOGP(DRLCMACMEAS, LOGL_ERROR,
|
|
|
|
"max_cs_ul cannot be derived (current UL CS: %s)\n",
|
|
|
|
mcs_name(ms->current_cs_ul));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ms->current_cs_ul) {
|
|
|
|
LOGP(DRLCMACMEAS, LOGL_ERROR,
|
|
|
|
"Unable to update UL (M)CS because it's not set: %s\n",
|
|
|
|
mcs_name(ms->current_cs_ul));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!meas->have_link_qual) {
|
|
|
|
LOGP(DRLCMACMEAS, LOGL_ERROR,
|
|
|
|
"Unable to update UL (M)CS %s because we don't have link quality measurements.\n",
|
|
|
|
mcs_name(ms->current_cs_ul));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mcs_is_gprs(ms->current_cs_ul)) {
|
|
|
|
if (current_cs >= MAX_GPRS_CS)
|
|
|
|
current_cs = MAX_GPRS_CS - 1;
|
2021-01-14 12:30:04 +00:00
|
|
|
low = the_pcu->vty.cs_lqual_ranges[current_cs].low;
|
|
|
|
high = the_pcu->vty.cs_lqual_ranges[current_cs].high;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
} else if (mcs_is_edge(ms->current_cs_ul)) {
|
|
|
|
if (current_cs >= MAX_EDGE_MCS)
|
|
|
|
current_cs = MAX_EDGE_MCS - 1;
|
2021-01-14 12:30:04 +00:00
|
|
|
low = the_pcu->vty.mcs_lqual_ranges[current_cs].low;
|
|
|
|
high = the_pcu->vty.mcs_lqual_ranges[current_cs].high;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
} else {
|
|
|
|
LOGP(DRLCMACMEAS, LOGL_ERROR,
|
|
|
|
"Unable to update UL (M)CS because it's neither GPRS nor EDGE: %s\n",
|
|
|
|
mcs_name(ms->current_cs_ul));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* To avoid rapid changes of the coding scheme, we also take
|
|
|
|
* the old link quality value into account (if present). */
|
|
|
|
if (ms->l1_meas.have_link_qual)
|
|
|
|
old_link_qual = ms->l1_meas.link_qual;
|
|
|
|
else
|
|
|
|
old_link_qual = meas->link_qual;
|
|
|
|
|
|
|
|
if (meas->link_qual < low && old_link_qual < low)
|
|
|
|
mcs_dec_kind(&new_cs_ul, ms_mode(ms));
|
|
|
|
else if (meas->link_qual > high && old_link_qual > high &&
|
|
|
|
ms->current_cs_ul < max_cs_ul)
|
|
|
|
mcs_inc_kind(&new_cs_ul, ms_mode(ms));
|
|
|
|
|
|
|
|
if (ms->current_cs_ul != new_cs_ul) {
|
|
|
|
LOGPMS(ms, DRLCMACMEAS, LOGL_INFO,
|
|
|
|
"Link quality %ddB (old %ddB) left window [%d, %d], "
|
|
|
|
"modifying uplink CS level: %s -> %s\n",
|
|
|
|
meas->link_qual, old_link_qual,
|
|
|
|
low, high,
|
|
|
|
mcs_name(ms->current_cs_ul), mcs_name(new_cs_ul));
|
|
|
|
|
|
|
|
ms->current_cs_ul = new_cs_ul;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_update_l1_meas(struct GprsMs *ms, const struct pcu_l1_meas *meas)
|
|
|
|
{
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
ms_update_cs_ul(ms, meas);
|
|
|
|
|
|
|
|
if (meas->have_rssi)
|
|
|
|
pcu_l1_meas_set_rssi(&ms->l1_meas, meas->rssi);
|
|
|
|
if (meas->have_bto)
|
|
|
|
pcu_l1_meas_set_bto(&ms->l1_meas, meas->bto);
|
|
|
|
if (meas->have_ber)
|
|
|
|
pcu_l1_meas_set_ber(&ms->l1_meas, meas->ber);
|
|
|
|
if (meas->have_link_qual)
|
|
|
|
pcu_l1_meas_set_link_qual(&ms->l1_meas, meas->link_qual);
|
|
|
|
|
|
|
|
if (meas->have_ms_rx_qual)
|
|
|
|
pcu_l1_meas_set_ms_rx_qual(&ms->l1_meas, meas->ms_rx_qual);
|
|
|
|
if (meas->have_ms_c_value)
|
|
|
|
pcu_l1_meas_set_ms_c_value(&ms->l1_meas, meas->ms_c_value);
|
|
|
|
if (meas->have_ms_sign_var)
|
|
|
|
pcu_l1_meas_set_ms_sign_var(&ms->l1_meas, meas->ms_sign_var);
|
|
|
|
|
|
|
|
if (meas->have_ms_i_level) {
|
|
|
|
for (i = 0; i < ARRAY_SIZE(meas->ts); ++i) {
|
|
|
|
if (meas->ts[i].have_ms_i_level)
|
|
|
|
pcu_l1_meas_set_ms_i_level(&ms->l1_meas, i, meas->ts[i].ms_i_level);
|
|
|
|
else
|
|
|
|
ms->l1_meas.ts[i].have_ms_i_level = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-25 11:05:32 +00:00
|
|
|
/* req_mcs_kind acts as a set filter, where EGPRS means any and GPRS is the most restrictive */
|
|
|
|
enum CodingScheme ms_current_cs_dl(const struct GprsMs *ms, enum mcs_kind req_mcs_kind)
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
{
|
2021-01-25 11:05:32 +00:00
|
|
|
enum CodingScheme orig_cs = ms->current_cs_dl;
|
|
|
|
struct gprs_rlcmac_bts *bts = ms->bts;
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
size_t unencoded_octets;
|
2021-01-25 11:05:32 +00:00
|
|
|
enum CodingScheme cs;
|
|
|
|
|
|
|
|
/* It could be that a TBF requests a GPRS CS despite the MS currently
|
|
|
|
being upgraded to EGPRS (hence reporting MCS). That could happen
|
|
|
|
because the TBF was created early in the process where we didn't have
|
|
|
|
yet enough information about the MS, and only AFTER it was created we
|
|
|
|
upgraded the MS to be EGPRS capable.
|
|
|
|
As a result, when the MS is queried for the target CS here, we could be
|
|
|
|
returning an MCS despite the current TBF being established as GPRS,
|
|
|
|
but we rather stick to the TBF type we assigned to the MS rather than
|
|
|
|
magically sending EGPRS data blocks to a GPRS TBF.
|
|
|
|
It could also be that the caller requests specific MCS kind
|
|
|
|
explicitly too due to scheduling restrictions (GPRS+EGPRS multiplexing). */
|
|
|
|
if (req_mcs_kind == EGPRS_GMSK && mcs_is_edge(orig_cs) && orig_cs > MCS4) {
|
|
|
|
cs = bts_cs_dl_is_supported(bts, MCS4) ? MCS4 :
|
|
|
|
bts_cs_dl_is_supported(bts, MCS3) ? MCS3 :
|
|
|
|
bts_cs_dl_is_supported(bts, MCS2) ? MCS2 :
|
|
|
|
MCS1;
|
|
|
|
} else if (req_mcs_kind == GPRS && mcs_is_edge(orig_cs)) { /* GPRS */
|
|
|
|
int i;
|
|
|
|
cs = orig_cs > MCS4 ? MCS4 : orig_cs;
|
|
|
|
cs -= (MCS1 - CS1); /* MCSx -> CSx */
|
|
|
|
/* Find suitable CS starting from equivalent MCS which is supported by BTS: */
|
|
|
|
for (i = mcs_chan_code(cs); !bts_cs_dl_is_supported(bts, CS1 + i); i--);
|
|
|
|
OSMO_ASSERT(i >= 0 && i <= 3); /* CS1 is always supported */
|
|
|
|
cs = CS1 + i;
|
|
|
|
} else {
|
|
|
|
cs = orig_cs;
|
|
|
|
}
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
2021-01-25 11:05:32 +00:00
|
|
|
if (orig_cs != cs)
|
|
|
|
LOGPMS(ms, DRLCMACDL, LOGL_INFO, "MS (mode=%s) suggests transmitting "
|
|
|
|
"DL %s, downgrade to %s in order to match TBF & scheduler requirements\n",
|
|
|
|
mode_name(ms_mode(ms)), mcs_name(orig_cs), mcs_name(cs));
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
|
|
|
|
unencoded_octets = llc_queue_octets(&ms->llc_queue);
|
|
|
|
|
|
|
|
/* If the DL TBF is active, add number of unencoded chunk octets */
|
|
|
|
if (ms->dl_tbf)
|
|
|
|
unencoded_octets += llc_chunk_size(tbf_llc((struct gprs_rlcmac_tbf *)ms->dl_tbf));
|
|
|
|
|
|
|
|
/* There are many unencoded octets, don't reduce */
|
2021-01-14 12:20:55 +00:00
|
|
|
if (unencoded_octets >= the_pcu->vty.cs_downgrade_threshold)
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
return cs;
|
|
|
|
|
|
|
|
/* RF conditions are good, don't reduce */
|
2021-01-14 12:17:01 +00:00
|
|
|
if (ms->nack_rate_dl < the_pcu->vty.cs_adj_lower_limit)
|
Convert GprsMS and helpers classes to C
As we integrate osmo-pcu more and more with libosmocore features, it
becomes really hard to use them since libosmocore relies heavily on C
specific compilation features, which are not available in old C++
compilers (such as designated initializers for complex types in FSMs).
GprsMs is right now a quite simple object since initial design of
osmo-pcu made it optional and most of the logic was placed and stored
duplicated in TBF objects. However, that's changing as we introduce more
features, with the GprsMS class getting more weight. Hence, let's move
it now to be a C struct in order to be able to easily use libosmocore
features there, such as FSMs.
Some helper classes which GprsMs uses are also mostly move to C since
they are mostly structs with methods, so there's no point in having
duplicated APIs for C++ and C for such simple cases.
For some more complex classes, like (ul_,dl_)tbf, C API bindings are
added where needed so that GprsMs can use functionalitites from that
class. Most of those APIs can be kept afterwards and drop the C++ ones
since they provide no benefit in general.
Change-Id: I0b50e3367aaad9dcada76da97b438e452c8b230c
2020-12-16 14:59:45 +00:00
|
|
|
return cs;
|
|
|
|
|
|
|
|
/* The throughput would probably be better if the CS level was reduced */
|
|
|
|
mcs_dec_kind(&cs, ms_mode(ms));
|
|
|
|
|
|
|
|
/* CS-2 doesn't gain throughput with small packets, further reduce to CS-1 */
|
|
|
|
if (cs == CS2)
|
|
|
|
mcs_dec_kind(&cs, ms_mode(ms));
|
|
|
|
|
|
|
|
return cs;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ms_first_common_ts(const struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
if (ms->dl_tbf)
|
|
|
|
return tbf_first_common_ts((struct gprs_rlcmac_tbf *)ms->dl_tbf);
|
|
|
|
|
|
|
|
if (ms->ul_tbf)
|
|
|
|
return tbf_first_common_ts((struct gprs_rlcmac_tbf *)ms->ul_tbf);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ms_dl_slots(const struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
uint8_t slots = 0;
|
|
|
|
|
|
|
|
if (ms->dl_tbf)
|
|
|
|
slots |= tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf);
|
|
|
|
|
|
|
|
if (ms->ul_tbf)
|
|
|
|
slots |= tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf);
|
|
|
|
|
|
|
|
return slots;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ms_ul_slots(const struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
uint8_t slots = 0;
|
|
|
|
|
|
|
|
if (ms->dl_tbf)
|
|
|
|
slots |= tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf);
|
|
|
|
|
|
|
|
if (ms->ul_tbf)
|
|
|
|
slots |= tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf);
|
|
|
|
|
|
|
|
return slots;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t ms_current_pacch_slots(const struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
uint8_t slots = 0;
|
|
|
|
|
|
|
|
bool is_dl_active = ms->dl_tbf && tbf_is_tfi_assigned((struct gprs_rlcmac_tbf *)ms->dl_tbf);
|
|
|
|
bool is_ul_active = ms->ul_tbf && tbf_is_tfi_assigned((struct gprs_rlcmac_tbf *)ms->ul_tbf);
|
|
|
|
|
|
|
|
if (!is_dl_active && !is_ul_active)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* see TS 44.060, 8.1.1.2.2 */
|
|
|
|
if (is_dl_active && !is_ul_active)
|
|
|
|
slots = tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf);
|
|
|
|
else if (!is_dl_active && is_ul_active)
|
|
|
|
slots = tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf);
|
|
|
|
else
|
|
|
|
slots = tbf_ul_slots((struct gprs_rlcmac_tbf *)ms->ul_tbf) &
|
|
|
|
tbf_dl_slots((struct gprs_rlcmac_tbf *)ms->dl_tbf);
|
|
|
|
|
|
|
|
/* Assume a multislot class 1 device */
|
|
|
|
/* TODO: For class 2 devices, this could be removed */
|
|
|
|
slots = pcu_lsb(slots);
|
|
|
|
|
|
|
|
return slots;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ms_set_reserved_slots(struct GprsMs *ms, struct gprs_rlcmac_trx *trx,
|
|
|
|
uint8_t ul_slots, uint8_t dl_slots)
|
|
|
|
{
|
|
|
|
if (ms->current_trx) {
|
|
|
|
bts_trx_unreserve_slots(ms->current_trx, GPRS_RLCMAC_DL_TBF,
|
|
|
|
ms->reserved_dl_slots);
|
|
|
|
bts_trx_unreserve_slots(ms->current_trx, GPRS_RLCMAC_UL_TBF,
|
|
|
|
ms->reserved_ul_slots);
|
|
|
|
ms->reserved_dl_slots = 0;
|
|
|
|
ms->reserved_ul_slots = 0;
|
|
|
|
}
|
|
|
|
ms->current_trx = trx;
|
|
|
|
if (trx) {
|
|
|
|
ms->reserved_dl_slots = dl_slots;
|
|
|
|
ms->reserved_ul_slots = ul_slots;
|
|
|
|
bts_trx_reserve_slots(ms->current_trx, GPRS_RLCMAC_DL_TBF,
|
|
|
|
ms->reserved_dl_slots);
|
|
|
|
bts_trx_reserve_slots(ms->current_trx, GPRS_RLCMAC_UL_TBF,
|
|
|
|
ms->reserved_ul_slots);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct gprs_rlcmac_tbf *ms_tbf(const struct GprsMs *ms, enum gprs_rlcmac_tbf_direction dir)
|
|
|
|
{
|
|
|
|
switch (dir) {
|
|
|
|
case GPRS_RLCMAC_DL_TBF: return (struct gprs_rlcmac_tbf *)ms->dl_tbf;
|
|
|
|
case GPRS_RLCMAC_UL_TBF: return (struct gprs_rlcmac_tbf *)ms->ul_tbf;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
Introduce NACC support
A new nacc_fsm is introduced per MS object, with its partner priv
structure struct nacc_fsm_ctx, which exists and is available in the MS
object only during the duration of the NACC procedure.
The NACC context is created on an MS whenever a Pkt Cell Change
Notification is received on Uplink RLCMAC, which asks for neighbor
information of a given ARFCN+BSIC.
First, the target ARFCN+BSIC needs to be translated into a CGI-PS
(RAC+CI) address. That's done by asking the BSC through the Neighbour
Resolution Service available in osmo-bsc using the CTRL interface.
Once the CGI-PS of the target cell is known, PCU starts a RIM RAN-INFO
request against the SGSN (which will route the request as needed), and
wait for a response containing the SI bits from the target cell.
After the SI are received, the scheduler is instructed to eventually
poll a TBF for the MS originating the CCN, so that we can send the SI
encapsulated into multiple Packet Neighbor Cell Data messages on the
downlink.
One all the SI bits are sent, the scheduler is instructed to send a
Packet Cell Change Continue message.
Once the message above has been sent, the FSM autodestroys itself.
Caches are also introduced in this patch which allows for re-using
recently known translations ARFCN+BSIC -> CGI-PS and CGI-PS -> SI_INFO
respectively.
Change-Id: Id35f40d05f3e081f32fddbf1fa34cb338db452ca
2021-01-21 17:46:13 +00:00
|
|
|
|
|
|
|
int ms_nacc_start(struct GprsMs *ms, Packet_Cell_Change_Notification_t *notif)
|
|
|
|
{
|
|
|
|
if (!ms->nacc)
|
|
|
|
ms->nacc = nacc_fsm_alloc(ms);
|
|
|
|
if (!ms->nacc)
|
|
|
|
return -EINVAL;
|
|
|
|
return osmo_fsm_inst_dispatch(ms->nacc->fi, NACC_EV_RX_CELL_CHG_NOTIFICATION, notif);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool ms_nacc_rts(const struct GprsMs *ms)
|
|
|
|
{
|
|
|
|
if (!ms->nacc)
|
|
|
|
return false;
|
|
|
|
if (ms->nacc->fi->state == NACC_ST_TX_NEIGHBOUR_DATA ||
|
|
|
|
ms->nacc->fi->state == NACC_ST_TX_CELL_CHG_CONTINUE)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-02-01 13:52:48 +00:00
|
|
|
struct msgb *ms_nacc_create_rlcmac_msg(struct GprsMs *ms, struct gprs_rlcmac_tbf *tbf, uint32_t fn, uint8_t ts)
|
Introduce NACC support
A new nacc_fsm is introduced per MS object, with its partner priv
structure struct nacc_fsm_ctx, which exists and is available in the MS
object only during the duration of the NACC procedure.
The NACC context is created on an MS whenever a Pkt Cell Change
Notification is received on Uplink RLCMAC, which asks for neighbor
information of a given ARFCN+BSIC.
First, the target ARFCN+BSIC needs to be translated into a CGI-PS
(RAC+CI) address. That's done by asking the BSC through the Neighbour
Resolution Service available in osmo-bsc using the CTRL interface.
Once the CGI-PS of the target cell is known, PCU starts a RIM RAN-INFO
request against the SGSN (which will route the request as needed), and
wait for a response containing the SI bits from the target cell.
After the SI are received, the scheduler is instructed to eventually
poll a TBF for the MS originating the CCN, so that we can send the SI
encapsulated into multiple Packet Neighbor Cell Data messages on the
downlink.
One all the SI bits are sent, the scheduler is instructed to send a
Packet Cell Change Continue message.
Once the message above has been sent, the FSM autodestroys itself.
Caches are also introduced in this patch which allows for re-using
recently known translations ARFCN+BSIC -> CGI-PS and CGI-PS -> SI_INFO
respectively.
Change-Id: Id35f40d05f3e081f32fddbf1fa34cb338db452ca
2021-01-21 17:46:13 +00:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
struct nacc_ev_create_rlcmac_msg_ctx data_ctx;
|
|
|
|
|
2021-02-01 13:52:48 +00:00
|
|
|
data_ctx = (struct nacc_ev_create_rlcmac_msg_ctx) {
|
|
|
|
.tbf = tbf,
|
|
|
|
.fn = fn,
|
|
|
|
.ts = ts,
|
|
|
|
.msg = NULL,
|
|
|
|
};
|
Introduce NACC support
A new nacc_fsm is introduced per MS object, with its partner priv
structure struct nacc_fsm_ctx, which exists and is available in the MS
object only during the duration of the NACC procedure.
The NACC context is created on an MS whenever a Pkt Cell Change
Notification is received on Uplink RLCMAC, which asks for neighbor
information of a given ARFCN+BSIC.
First, the target ARFCN+BSIC needs to be translated into a CGI-PS
(RAC+CI) address. That's done by asking the BSC through the Neighbour
Resolution Service available in osmo-bsc using the CTRL interface.
Once the CGI-PS of the target cell is known, PCU starts a RIM RAN-INFO
request against the SGSN (which will route the request as needed), and
wait for a response containing the SI bits from the target cell.
After the SI are received, the scheduler is instructed to eventually
poll a TBF for the MS originating the CCN, so that we can send the SI
encapsulated into multiple Packet Neighbor Cell Data messages on the
downlink.
One all the SI bits are sent, the scheduler is instructed to send a
Packet Cell Change Continue message.
Once the message above has been sent, the FSM autodestroys itself.
Caches are also introduced in this patch which allows for re-using
recently known translations ARFCN+BSIC -> CGI-PS and CGI-PS -> SI_INFO
respectively.
Change-Id: Id35f40d05f3e081f32fddbf1fa34cb338db452ca
2021-01-21 17:46:13 +00:00
|
|
|
|
|
|
|
rc = osmo_fsm_inst_dispatch(ms->nacc->fi, NACC_EV_CREATE_RLCMAC_MSG, &data_ctx);
|
|
|
|
if (rc != 0 || !data_ctx.msg)
|
|
|
|
return NULL;
|
|
|
|
return data_ctx.msg;
|
|
|
|
}
|