aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bts.cpp45
-rw-r--r--src/bts.h5
-rw-r--r--src/gprs_pcu.c16
-rw-r--r--src/gprs_pcu.h3
-rw-r--r--src/pdch.cpp10
-rw-r--r--src/pdch.h1
-rw-r--r--tests/alloc/AllocTest.cpp4
7 files changed, 84 insertions, 0 deletions
diff --git a/src/bts.cpp b/src/bts.cpp
index 6fabc90c..63525e54 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -83,6 +83,20 @@ static struct osmo_tdef T_defs_bts[] = {
{ .T=3191, .default_val=5, .unit=OSMO_TDEF_S, .desc="Reuse of TFI(s) after sending (1) last RLC Data Block on TBF(s), or (2) PACKET TBF RELEASE for an MBMS radio bearer", .val=0 },
{ .T=3193, .default_val=100, .unit=OSMO_TDEF_MS, .desc="Reuse of TFI(s) after reception of final PACKET DOWNLINK ACK/NACK from MS for TBF", .val=0 },
{ .T=3195, .default_val=5, .unit=OSMO_TDEF_S, .desc="Reuse of TFI(s) upon no response from the MS (radio failure or cell change) for TBF/MBMS radio bearer", .val=0 },
+ { .T = -16, .default_val = 1000, .unit = OSMO_TDEF_MS,
+ .desc = "Granularity for *:all_allocated rate counters: amount of milliseconds that one counter increment"
+ " represents. See also X17, X18" },
+ { .T = -17, .default_val = 0, .unit = OSMO_TDEF_MS,
+ .desc = "Rounding threshold for *:all_allocated rate counters: round up to the next counter increment"
+ " after this many milliseconds. If set to half of X16 (or 0), employ the usual round() behavior:"
+ " round up after half of a granularity period. If set to 1, behave like ceil(): already"
+ " increment the counter immediately when all channels are allocated. If set >= X16, behave like"
+ " floor(): only increment after a full X16 period of all channels being occupied."
+ " See also X16, X18" },
+ { .T = -18, .default_val = 60000, .unit = OSMO_TDEF_MS,
+ .desc = "Forget-sum period for *:all_allocated rate counters:"
+ " after this amount of idle time, forget internally cumulated time remainders. Zero to always"
+ " keep remainders. See also X16, X17." },
{ .T=0, .default_val=0, .unit=OSMO_TDEF_S, .desc=NULL, .val=0 } /* empty item at the end */
};
@@ -92,6 +106,7 @@ static struct osmo_tdef T_defs_bts[] = {
* the code below.
*/
static const struct rate_ctr_desc bts_ctr_description[] = {
+ { "pdch:all_allocated", "Cumulative counter of seconds where all enabled PDCH resources were allocated"},
{ "tbf:dl:alloc", "TBF DL Allocated "},
{ "tbf:dl:freed", "TBF DL Freed "},
{ "tbf:dl:aborted", "TBF DL Aborted "},
@@ -231,6 +246,8 @@ static int bts_talloc_destructor(struct gprs_rlcmac_bts* bts)
bts->ms_store->cleanup();
delete bts->ms_store;
+ osmo_time_cc_cleanup(&bts->all_allocated_pdch);
+
if (bts->ratectrs) {
rate_ctr_group_free(bts->ratectrs);
bts->ratectrs = NULL;
@@ -300,6 +317,17 @@ struct gprs_rlcmac_bts* bts_alloc(struct gprs_pcu *pcu, uint8_t bts_nr)
bts->statg = osmo_stat_item_group_alloc(tall_pcu_ctx, &bts_statg_desc, 0);
OSMO_ASSERT(bts->statg);
+ osmo_time_cc_init(&bts->all_allocated_pdch);
+ bts->all_allocated_pdch.cfg = (struct osmo_time_cc_cfg){
+ .gran_usec = 1*1000000,
+ .forget_sum_usec = 60*1000000,
+ .rate_ctr = rate_ctr_group_get_ctr(bts->ratectrs, CTR_PDCH_ALL_ALLOCATED),
+ .T_gran = -16,
+ .T_round_threshold = -17,
+ .T_forget_sum = -18,
+ .T_defs = T_defs_bts,
+ };
+
llist_add_tail(&bts->list, &pcu->bts_list);
INIT_LLIST_HEAD(&bts->pch_timer);
@@ -1371,3 +1399,20 @@ uint8_t bts_get_ms_pwr_alpha(const struct gprs_rlcmac_bts *bts)
* B.2 Closed loop control */
return 0;
}
+
+/* Used by counter availablePDCHAllocatedTime, TS 52.402 B.2.1.45 "All available PDCH allocated time" */
+bool bts_all_pdch_allocated(const struct gprs_rlcmac_bts *bts)
+{
+ unsigned trx_no, ts_no;
+ for (trx_no = 0; trx_no < ARRAY_SIZE(bts->trx); trx_no++) {
+ const struct gprs_rlcmac_trx *trx = &bts->trx[trx_no];
+ for (ts_no = 0; ts_no < ARRAY_SIZE(trx->pdch); ts_no++) {
+ const struct gprs_rlcmac_pdch *pdch = &trx->pdch[ts_no];
+ if (!pdch_is_enabled(pdch))
+ continue;
+ if(!pdch_is_full(pdch))
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/src/bts.h b/src/bts.h
index f947a558..6bf62c73 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -32,6 +32,7 @@ extern "C" {
#include <osmocom/core/rate_ctr.h>
#include <osmocom/core/stat_item.h>
#include <osmocom/core/tdef.h>
+#include <osmocom/core/time_cc.h>
#include <osmocom/gprs/gprs_ns2.h>
#include <osmocom/gsm/l1sap.h>
#include <osmocom/gsm/protocol/gsm_04_08.h>
@@ -84,6 +85,7 @@ void bts_update_tbf_ta(struct gprs_rlcmac_bts *bts, const char *p, uint32_t fn,
enum {
+ CTR_PDCH_ALL_ALLOCATED,
CTR_TBF_DL_ALLOCATED,
CTR_TBF_DL_FREED,
CTR_TBF_DL_ABORTED,
@@ -278,6 +280,8 @@ struct gprs_rlcmac_bts {
/* List of struct bts_pch_timer for active PCH pagings */
struct llist_head pch_timer;
+
+ struct osmo_time_cc all_allocated_pdch;
};
#ifdef __cplusplus
@@ -381,6 +385,7 @@ void bts_set_max_mcs_ul(struct gprs_rlcmac_bts *bts, uint8_t mcs_ul);
bool bts_cs_dl_is_supported(const struct gprs_rlcmac_bts *bts, enum CodingScheme cs);
const struct llist_head* bts_ms_list(struct gprs_rlcmac_bts *bts);
uint8_t bts_get_ms_pwr_alpha(const struct gprs_rlcmac_bts *bts);
+bool bts_all_pdch_allocated(const struct gprs_rlcmac_bts *bts);
#ifdef __cplusplus
}
#endif
diff --git a/src/gprs_pcu.c b/src/gprs_pcu.c
index 5ed9d7d6..8b8e46b1 100644
--- a/src/gprs_pcu.c
+++ b/src/gprs_pcu.c
@@ -47,8 +47,21 @@ static struct osmo_tdef T_defs_pcu[] = {
{ .T=0, .default_val=0, .unit=OSMO_TDEF_S, .desc=NULL, .val=0 } /* empty item at the end */
};
+static void _update_stats_timer_cb(void *data)
+{
+ struct gprs_pcu *pcu = (struct gprs_pcu *)data;
+ struct gprs_rlcmac_bts *bts;
+
+ llist_for_each_entry(bts, &pcu->bts_list, list)
+ osmo_time_cc_set_flag(&bts->all_allocated_pdch, bts_all_pdch_allocated(bts));
+
+ osmo_timer_schedule(&pcu->update_stats_timer, 1, 0);
+}
+
static int gprs_pcu_talloc_destructor(struct gprs_pcu *pcu)
{
+ if (osmo_timer_pending(&pcu->update_stats_timer))
+ osmo_timer_del(&pcu->update_stats_timer);
neigh_cache_free(pcu->neigh_cache);
si_cache_free(pcu->si_cache);
return 0;
@@ -125,6 +138,9 @@ struct gprs_pcu *gprs_pcu_alloc(void *ctx)
pcu->neigh_cache = neigh_cache_alloc(pcu, osmo_tdef_get(pcu->T_defs, PCU_TDEF_NEIGH_CACHE_ALIVE, OSMO_TDEF_S, -1));
pcu->si_cache = si_cache_alloc(pcu, osmo_tdef_get(pcu->T_defs, PCU_TDEF_SI_CACHE_ALIVE, OSMO_TDEF_S, -1));
+ osmo_timer_setup(&pcu->update_stats_timer, _update_stats_timer_cb, pcu);
+ osmo_timer_schedule(&pcu->update_stats_timer, 1, 0);
+
return pcu;
}
diff --git a/src/gprs_pcu.h b/src/gprs_pcu.h
index ed002213..a9e40ea6 100644
--- a/src/gprs_pcu.h
+++ b/src/gprs_pcu.h
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include <osmocom/core/gsmtap_util.h>
+#include <osmocom/core/timer.h>
#include "gprs_bssgp_pcu.h"
#include "coding_scheme.h"
@@ -131,6 +132,8 @@ struct gprs_pcu {
struct neigh_cache *neigh_cache; /* ARFC+BSIC -> CGI PS cache */
struct si_cache *si_cache; /* ARFC+BSIC -> CGI PS cache */
+
+ struct osmo_timer_list update_stats_timer; /* Used to update some time_cc stats periodically */
};
diff --git a/src/pdch.cpp b/src/pdch.cpp
index a942b012..a5eb0804 100644
--- a/src/pdch.cpp
+++ b/src/pdch.cpp
@@ -1286,3 +1286,13 @@ bool pdch_is_enabled(const struct gprs_rlcmac_pdch *pdch)
{
return pdch->is_enabled();
}
+
+/* To be called only on enabled PDCHs. Used to gather information on whether the
+ * PDCH is currently unable to allocate more TBFs due to any resource being
+ * full. Used by bts_all_pdch_allocated() for counting purposes. */
+bool pdch_is_full(const struct gprs_rlcmac_pdch *pdch)
+{
+ return pdch->assigned_tfi(GPRS_RLCMAC_UL_TBF) == NO_FREE_TFI ||
+ pdch->assigned_tfi(GPRS_RLCMAC_DL_TBF) == NO_FREE_TFI ||
+ find_free_usf(pdch->assigned_usf()) < 0;
+}
diff --git a/src/pdch.h b/src/pdch.h
index 94056069..759d7f97 100644
--- a/src/pdch.h
+++ b/src/pdch.h
@@ -194,6 +194,7 @@ void pdch_init(struct gprs_rlcmac_pdch *pdch, struct gprs_rlcmac_trx *trx, uint8
void pdch_free_all_tbf(struct gprs_rlcmac_pdch *pdch);
void pdch_disable(struct gprs_rlcmac_pdch *pdch);
bool pdch_is_enabled(const struct gprs_rlcmac_pdch *pdch);
+bool pdch_is_full(const struct gprs_rlcmac_pdch *pdch);
#ifdef __cplusplus
}
#endif
diff --git a/tests/alloc/AllocTest.cpp b/tests/alloc/AllocTest.cpp
index 1f2bbdae..6f3de43d 100644
--- a/tests/alloc/AllocTest.cpp
+++ b/tests/alloc/AllocTest.cpp
@@ -152,6 +152,8 @@ static void test_alloc_a(gprs_rlcmac_tbf_direction dir,
OSMO_ASSERT(i == count);
+ OSMO_ASSERT(bts_all_pdch_allocated(bts));
+
for (i = 0; i < count; ++i)
if (tbfs[i])
tbf_free(tbfs[i]);
@@ -479,6 +481,7 @@ static GprsMs *alloc_tbfs(struct gprs_rlcmac_bts *bts, struct GprsMs *old_ms, en
tbf_free(ms_ul_tbf(old_ms));
tbf = tbf_alloc_ul_tbf(bts, old_ms, trx_no, false);
if (tbf == NULL) {
+ OSMO_ASSERT(trx_no != -1 || bts_all_pdch_allocated(bts));
ms_unref(old_ms);
return NULL;
}
@@ -490,6 +493,7 @@ static GprsMs *alloc_tbfs(struct gprs_rlcmac_bts *bts, struct GprsMs *old_ms, en
tbf_free(ms_dl_tbf(old_ms));
tbf = tbf_alloc_dl_tbf(bts, old_ms, trx_no, false);
if (tbf == NULL) {
+ OSMO_ASSERT(trx_no != -1 || bts_all_pdch_allocated(bts));
ms_unref(old_ms);
return NULL;
}