aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmocom/bsc/gsm_data.h1
-rw-r--r--include/osmocom/bsc/gsm_timers.h2
-rw-r--r--src/osmo-bsc/bsc_vty.c52
-rw-r--r--src/osmo-bsc/gsm_data.c1
-rw-r--r--src/osmo-bsc/gsm_timers_vty.c2
-rw-r--r--src/osmo-bsc/net_init.c2
-rw-r--r--src/osmo-bsc/paging.c30
7 files changed, 86 insertions, 4 deletions
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index 0b472a47b..e57da55c0 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -1147,6 +1147,7 @@ struct gsm_bts {
/* BTS-specific overrides for timer values from struct gsm_network. */
uint8_t T3122; /* ASSIGMENT REJECT wait indication */
+ bool T3113_dynamic; /* Calculate T3113 timeout dynamically based on BTS channel config and load */
/* Periodic channel load measurements are used to maintain T3122. */
struct load_counter chan_load_samples[7];
diff --git a/include/osmocom/bsc/gsm_timers.h b/include/osmocom/bsc/gsm_timers.h
index 78f04edd9..699c461ad 100644
--- a/include/osmocom/bsc/gsm_timers.h
+++ b/include/osmocom/bsc/gsm_timers.h
@@ -37,7 +37,7 @@ struct T_def *T_def_get_entry(struct T_def *T_defs, int T);
void T_defs_vty_init(struct T_def *T_defs, int cfg_parent_node);
void T_defs_vty_write(struct vty *vty, const char *indent);
-
+struct T_def *parse_T_arg(struct vty *vty, const char *T_str);
struct state_timeout {
int T;
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 983dcb9b3..8c7d8e19d 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -3951,6 +3951,56 @@ DEFUN(cfg_bts_amr_hr_hyst3, cfg_bts_amr_hr_hyst3_cmd,
return check_amr_config(vty);
}
+#define TNUM_STR "T-number, optionally preceded by 't' or 'T'\n"
+DEFUN(cfg_bts_t3113_dynamic, cfg_bts_t3113_dynamic_cmd,
+ "timer-dynamic TNNNN",
+ "Calculate T3113 dynamically based on channel config and load\n"
+ TNUM_STR)
+{
+ struct T_def *d;
+ struct gsm_bts *bts = vty->index;
+
+ d = parse_T_arg(vty, argv[0]);
+ if (!d)
+ return CMD_WARNING;
+
+ switch (d->T) {
+ case 3113:
+ bts->T3113_dynamic = true;
+ break;
+ default:
+ vty_out(vty, "T%d cannot be set to dynamic%s", d->T, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_bts_no_t3113_dynamic, cfg_bts_no_t3113_dynamic_cmd,
+ "no timer-dynamic TNNNN",
+ NO_STR
+ "Set given timer to non-dynamic and use the default or user provided fixed value\n"
+ TNUM_STR)
+{
+ struct T_def *d;
+ struct gsm_bts *bts = vty->index;
+
+ d = parse_T_arg(vty, argv[0]);
+ if (!d)
+ return CMD_WARNING;
+
+ switch (d->T) {
+ case 3113:
+ bts->T3113_dynamic = false;
+ break;
+ default:
+ vty_out(vty, "T%d already is non-dynamic%s", d->T, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
#define TRX_TEXT "Radio Transceiver\n"
/* per TRX configuration */
@@ -5129,6 +5179,8 @@ int bsc_vty_init(struct gsm_network *network)
install_element(BTS_NODE, &cfg_bts_no_acc_ramping_cmd);
install_element(BTS_NODE, &cfg_bts_acc_ramping_step_interval_cmd);
install_element(BTS_NODE, &cfg_bts_acc_ramping_step_size_cmd);
+ install_element(BTS_NODE, &cfg_bts_t3113_dynamic_cmd);
+ install_element(BTS_NODE, &cfg_bts_no_t3113_dynamic_cmd);
neighbor_ident_vty_init(network, network->neighbor_bss_cells);
/* See also handover commands added on bts level from handover_vty.c */
diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c
index 6d39642e2..0f76a2746 100644
--- a/src/osmo-bsc/gsm_data.c
+++ b/src/osmo-bsc/gsm_data.c
@@ -849,6 +849,7 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num)
/* timer overrides */
bts->T3122 = 0; /* not overriden by default */
+ bts->T3113_dynamic = true; /* dynamic by default */
bts->dtxu = GSM48_DTX_SHALL_NOT_BE_USED;
bts->dtxd = false;
diff --git a/src/osmo-bsc/gsm_timers_vty.c b/src/osmo-bsc/gsm_timers_vty.c
index de61e2453..e744dfac5 100644
--- a/src/osmo-bsc/gsm_timers_vty.c
+++ b/src/osmo-bsc/gsm_timers_vty.c
@@ -32,7 +32,7 @@ static struct T_def *g_vty_T_defs = NULL;
/* Parse an argument like "T1234", "t1234" or "1234" and return the corresponding T_def entry from
* g_vty_T_defs, if any. */
-static struct T_def *parse_T_arg(struct vty *vty, const char *T_str)
+struct T_def *parse_T_arg(struct vty *vty, const char *T_str)
{
int T;
struct T_def *d;
diff --git a/src/osmo-bsc/net_init.c b/src/osmo-bsc/net_init.c
index 1199bdc82..5ea564d70 100644
--- a/src/osmo-bsc/net_init.c
+++ b/src/osmo-bsc/net_init.c
@@ -37,7 +37,7 @@ static struct T_def gsm_network_T_defs[] = {
{ .T=3109, .default_val=5, .desc="RSL SACCH deactivation" },
{ .T=3111, .default_val=2, .desc="Wait time before RSL RF Channel Release" },
{ .T=993111, .default_val=4, .desc="Wait time after lchan was released in error (should be T3111 + 2s)" },
- { .T=3113, .default_val=10, .desc="Paging"},
+ { .T=3113, .default_val=7, .desc="Paging"},
{ .T=3115, .default_val=10, .desc="(unused)" },
{ .T=3117, .default_val=10, .desc="(unused)" },
{ .T=3119, .default_val=10, .desc="(unused)" },
diff --git a/src/osmo-bsc/paging.c b/src/osmo-bsc/paging.c
index afe32453e..246114f74 100644
--- a/src/osmo-bsc/paging.c
+++ b/src/osmo-bsc/paging.c
@@ -287,6 +287,32 @@ static void paging_T3113_expired(void *data)
paging_remove_request(&req->bts->paging, req);
}
+#define GSM_FRAME_DURATION_us 4615
+#define GSM51_MFRAME_DURATION_us (51 * GSM_FRAME_DURATION_us) /* 235365 us */
+static unsigned int calculate_timer_3113(struct gsm_bts *bts)
+{
+ unsigned int to_us, to;
+ struct T_def *d = T_def_get_entry(bts->network->T_defs, 3113);
+
+ if (!bts->T3113_dynamic)
+ return d->val;
+
+ /* TODO: take into account load of paging group for req->bsub */
+
+ /* MFRMS defines repeat interval of paging messages for MSs that belong
+ * to same paging group accross multiple 51 frame multiframes.
+ * MAXTRANS defines maximum number of RACH retransmissions.
+ */
+ to_us = GSM51_MFRAME_DURATION_us * (bts->si_common.chan_desc.bs_pa_mfrms + 2) *
+ bts->si_common.rach_control.max_trans;
+
+ /* ceiling in seconds + extra time */
+ to = (to_us + 999999) / 1000000 + d->val;
+ LOGP(DPAG, LOGL_DEBUG, "(bts=%d) Paging request: T3113 expires in %u seconds\n",
+ bts->nr, to);
+ return to;
+}
+
/*! Start paging + paging timer for given subscriber on given BTS
* \param bts BTS on which to page
* \param[in] bsub subscriber we want to page
@@ -298,6 +324,7 @@ static int _paging_request(struct gsm_bts *bts, struct bsc_subscr *bsub, int typ
{
struct gsm_bts_paging_state *bts_entry = &bts->paging;
struct gsm_paging_request *req;
+ unsigned int t3113_timeout_s;
rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_PAGING_ATTEMPTED]);
@@ -317,7 +344,8 @@ static int _paging_request(struct gsm_bts *bts, struct bsc_subscr *bsub, int typ
req->chan_type = type;
req->msc = msc;
osmo_timer_setup(&req->T3113, paging_T3113_expired, req);
- osmo_timer_schedule(&req->T3113, T_def_get(bts->network->T_defs, 3113, T_S, -1), 0);
+ t3113_timeout_s = calculate_timer_3113(bts);
+ osmo_timer_schedule(&req->T3113, t3113_timeout_s, 0);
llist_add_tail(&req->entry, &bts_entry->pending_requests);
paging_schedule_if_needed(bts_entry);