From a1944d434e1b53b55773df604881206253973db1 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Sat, 16 Jun 2018 19:29:50 +0200 Subject: add gsm_timers, for Tnnn definitions usable by FSMs Change-Id: If212fcd042051b6fa53484254223614c5b93a9c6 --- include/osmocom/bsc/Makefile.am | 1 + include/osmocom/bsc/gsm_data.h | 41 +----- include/osmocom/bsc/gsm_timers.h | 55 +++++++ src/ipaccess/Makefile.am | 2 + src/osmo-bsc/Makefile.am | 2 + src/osmo-bsc/abis_om2000.c | 10 +- src/osmo-bsc/abis_rsl.c | 20 +-- src/osmo-bsc/bsc_subscr_conn_fsm.c | 60 +++++--- src/osmo-bsc/bsc_vty.c | 102 ++----------- src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c | 3 +- src/osmo-bsc/bts_siemens_bs11.c | 3 +- src/osmo-bsc/gsm_data.c | 3 +- src/osmo-bsc/gsm_timers.c | 206 +++++++++++++++++++++++++++ src/osmo-bsc/gsm_timers_vty.c | 117 +++++++++++++++ src/osmo-bsc/net_init.c | 49 ++++--- src/osmo-bsc/paging.c | 3 +- src/utils/Makefile.am | 2 + tests/abis/Makefile.am | 1 + tests/bsc/Makefile.am | 1 + tests/gsm0408/Makefile.am | 1 + tests/handover/Makefile.am | 1 + tests/nanobts_omlattr/Makefile.am | 1 + tests/nanobts_omlattr/nanobts_omlattr_test.c | 9 ++ 23 files changed, 513 insertions(+), 180 deletions(-) create mode 100644 include/osmocom/bsc/gsm_timers.h create mode 100644 src/osmo-bsc/gsm_timers.c create mode 100644 src/osmo-bsc/gsm_timers_vty.c diff --git a/include/osmocom/bsc/Makefile.am b/include/osmocom/bsc/Makefile.am index 18737a390..82a2e26cd 100644 --- a/include/osmocom/bsc/Makefile.am +++ b/include/osmocom/bsc/Makefile.am @@ -18,6 +18,7 @@ noinst_HEADERS = \ gsm_04_08_utils.h \ gsm_04_80.h \ gsm_data.h \ + gsm_timers.h \ handover.h \ handover_cfg.h \ handover_decision.h \ diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h index 287249382..272b192ce 100644 --- a/include/osmocom/bsc/gsm_data.h +++ b/include/osmocom/bsc/gsm_data.h @@ -32,6 +32,8 @@ #include #include +#define GSM_T3122_DEFAULT 10 + struct mgcp_client_conf; struct mgcp_client; struct mgcp_ctx; @@ -1192,23 +1194,6 @@ static const struct rate_ctr_group_desc bsc_ctrg_desc = { bsc_ctr_description, }; -#define GSM_T3101_DEFAULT 3 /* s */ -#define GSM_T3103_DEFAULT 5 /* s */ -#define GSM_T3105_DEFAULT 100 /* ms */ -#define GSM_T3107_DEFAULT 5 /* s */ -#define GSM_T3109_DEFAULT 5 /* s, must be 2s + radio_link_timeout*0.48 */ -#define GSM_T3111_DEFAULT 2 /* s */ -#define GSM_T3113_DEFAULT 10 /* s */ -#define GSM_T3115_DEFAULT 10 -#define GSM_T3117_DEFAULT 10 -#define GSM_T3119_DEFAULT 10 -#define GSM_T3122_DEFAULT 10 -#define GSM_T3141_DEFAULT 10 -#define GSM_T10_DEFAULT 6 /* RR Assignment timeout, in seconds */ -#define GSM_T7_DEFAULT 10 /* inter-BSC MO Handover first timeout, in seconds */ -#define GSM_T8_DEFAULT 10 /* inter-BSC MO Handover second timeout, in seconds */ -#define GSM_T101_DEFAULT 10 /* inter-BSC MT Handover timeout, in seconds */ - struct gsm_tz { int override; /* if 0, use system's time zone instead. */ int hr; /* hour */ @@ -1240,23 +1225,8 @@ struct gsm_network { unsigned int num_bts; struct llist_head bts_list; - /* timer values */ - int T3101; - int T3103; /*< Handover timeout */ - int T3105; - int T3107; - int T3109; - int T3111; - int T3113; - int T3115; - int T3117; - int T3119; - int T3122; - int T3141; - int T10; /*< RR Assignment timeout, in seconds */ - int T7; /*< inter-BSC handover MO timeout from Handover Required to Handover Command */ - int T8; /*< inter-BSC handover MO timeout from Handover Command to final Clear*/ - int T101; /*< inter-BSC handover MT timeout from Handover Request to Handover Accept */ + /* shall reference gsm_network_T[] */ + struct T_def *T_defs; enum gsm_chan_t ctype_by_chreq[_NUM_CHREQ_T]; @@ -1290,9 +1260,6 @@ struct gsm_network { * pointer is NULL to indicate absence of a bsc_subscribers list. */ struct llist_head *bsc_subscribers; - /* Periodic location update default value */ - uint8_t t3212; - /* Timer for periodic channel load measurements to maintain each BTS's T3122. */ struct osmo_timer_list t3122_chan_load_timer; diff --git a/include/osmocom/bsc/gsm_timers.h b/include/osmocom/bsc/gsm_timers.h new file mode 100644 index 000000000..fde8c93c0 --- /dev/null +++ b/include/osmocom/bsc/gsm_timers.h @@ -0,0 +1,55 @@ +/* API to define Tnnn timers globally, configure in VTY and use for FSM state changes. */ +#pragma once + +#include +#include + +struct osmo_fsm_inst; +struct vty; + +enum T_unit { + T_S = 0, /*< most T are in seconds, keep 0 as default. */ + T_MS, /*< milliseconds */ + T_M, /*< minutes */ + T_CUSTOM, +}; + +extern const struct value_string T_unit_names[]; +static inline const char *T_unit_name(enum T_unit val) +{ return get_value_string(T_unit_names, val); } + +/* Define a GSM timer of the form Tnnn, with unit, default value and doc string. */ +struct T_def { + const int T; /*< T1234 number */ + const int default_val; /*< timeout duration (according to unit), default value. */ + const enum T_unit unit; + const char *desc; + int val; /*< currently active value, e.g. set by user config. */ +}; + +/* Iterate an array of struct T_def, the last item should be fully zero, i.e. "{}" */ +#define for_each_T_def(d, T_defs) \ + for (d = T_defs; d && (d->T || d->default_val || d->desc); d++) + +int T_def_get(struct T_def *T_defs, int T, enum T_unit as_unit, int val_if_not_present); +void T_defs_reset(struct T_def *T_defs); +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 state_timeout { + int T; + bool keep_timer; +}; + +struct state_timeout *get_state_timeout(uint32_t state, struct state_timeout *timeouts_array); + +#define fsm_inst_state_chg_T(fi, state, timeouts_array, T_defs, default_timeout) \ + _fsm_inst_state_chg_T(fi, state, timeouts_array, T_defs, default_timeout, \ + __FILE__, __LINE__) +int _fsm_inst_state_chg_T(struct osmo_fsm_inst *fi, uint32_t state, + struct state_timeout *timeouts_array, + struct T_def *T_defs, int default_timeout, + const char *file, int line); diff --git a/src/ipaccess/Makefile.am b/src/ipaccess/Makefile.am index 2c6282d11..ec3e02705 100644 --- a/src/ipaccess/Makefile.am +++ b/src/ipaccess/Makefile.am @@ -55,6 +55,7 @@ ipaccess_config_LDADD = \ $(top_builddir)/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.o \ $(top_builddir)/src/osmo-bsc/gsm_data.o \ $(top_builddir)/src/osmo-bsc/net_init.o \ + $(top_builddir)/src/osmo-bsc/gsm_timers.o \ $(OSMO_LIBS) \ $(NULL) @@ -65,5 +66,6 @@ ipaccess_proxy_SOURCES = \ $(NULL) ipaccess_proxy_LDADD = \ + $(top_builddir)/src/osmo-bsc/gsm_timers.o \ $(OSMO_LIBS) \ $(NULL) diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am index afae0b66b..86d943f4a 100644 --- a/src/osmo-bsc/Makefile.am +++ b/src/osmo-bsc/Makefile.am @@ -57,6 +57,8 @@ osmo_bsc_SOURCES = \ gsm_04_08_utils.c \ gsm_04_80_utils.c \ gsm_data.c \ + gsm_timers.c \ + gsm_timers_vty.c \ handover_cfg.c \ handover_decision.c \ handover_decision_2.c \ diff --git a/src/osmo-bsc/abis_om2000.c b/src/osmo-bsc/abis_om2000.c index d533ea198..293459087 100644 --- a/src/osmo-bsc/abis_om2000.c +++ b/src/osmo-bsc/abis_om2000.c @@ -42,6 +42,7 @@ #include #include #include +#include #include /* FIXME: move to libosmocore */ @@ -1382,7 +1383,8 @@ int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts) msgb_tv_put(msg, OM2K_DEI_CCCH_OPTIONS, 0x01); break; case GSM_PCHAN_CCCH_SDCCH4: - msgb_tv_put(msg, OM2K_DEI_T3105, ts->trx->bts->network->T3105 / 10); + msgb_tv_put(msg, OM2K_DEI_T3105, + T_def_get(ts->trx->bts->network->T_defs, 3105, T_MS, -1) / 10); msgb_tv_put(msg, OM2K_DEI_NY1, 35); msgb_tv_put(msg, OM2K_DEI_BA_PA_MFRMS, 0x06); msgb_tv_put(msg, OM2K_DEI_CBCH_INDICATOR, 0); @@ -1396,7 +1398,8 @@ int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts) sizeof(icm_bound_params), icm_bound_params); break; case GSM_PCHAN_SDCCH8_SACCH8C: - msgb_tv_put(msg, OM2K_DEI_T3105, ts->trx->bts->network->T3105 / 10); + msgb_tv_put(msg, OM2K_DEI_T3105, + T_def_get(ts->trx->bts->network->T_defs, 3105, T_MS, -1) / 10); msgb_tv_put(msg, OM2K_DEI_NY1, 35); msgb_tv_put(msg, OM2K_DEI_CBCH_INDICATOR, 0); msgb_tv_put(msg, OM2K_DEI_TSC, gsm_ts_tsc(ts)); @@ -1406,7 +1409,8 @@ int abis_om2k_tx_ts_conf_req(struct gsm_bts_trx_ts *ts) sizeof(icm_bound_params), icm_bound_params); break; default: - msgb_tv_put(msg, OM2K_DEI_T3105, ts->trx->bts->network->T3105 / 10); + msgb_tv_put(msg, OM2K_DEI_T3105, + T_def_get(ts->trx->bts->network->T_defs, 3105, T_MS, -1) / 10); msgb_tv_put(msg, OM2K_DEI_NY1, 35); msgb_tv_put(msg, OM2K_DEI_TSC, gsm_ts_tsc(ts)); /* Disable RF RESOURCE INDICATION on idle channels */ diff --git a/src/osmo-bsc/abis_rsl.c b/src/osmo-bsc/abis_rsl.c index a40038c75..fddf7c56e 100644 --- a/src/osmo-bsc/abis_rsl.c +++ b/src/osmo-bsc/abis_rsl.c @@ -46,6 +46,7 @@ #include #include #include +#include #define RSL_ALLOC_SIZE 1024 #define RSL_ALLOC_HEADROOM 128 @@ -81,7 +82,9 @@ static void do_lchan_free(struct gsm_lchan *lchan) if (lchan->state == LCHAN_S_REL_ERR) { osmo_timer_setup(&lchan->error_timer, error_timeout_cb, lchan); osmo_timer_schedule(&lchan->error_timer, - lchan->ts->trx->bts->network->T3111 + 2, 0); + T_def_get(lchan->ts->trx->bts->network->T_defs, + 993111, T_S, -1), + 0); } else { rsl_lchan_set_state(lchan, LCHAN_S_NONE); } @@ -1915,11 +1918,10 @@ static int rsl_rx_chan_rqd(struct msgb *msg) LOGP(DRSL, LOGL_NOTICE, "(bts=%d) CHAN RQD: no resources for %s 0x%x\n", msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra); rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_CHREQ_NO_CHANNEL]); - if (bts->T3122) - wait_ind = bts->T3122; - else if (bts->network->T3122) - wait_ind = bts->network->T3122 & 0xff; - else + wait_ind = bts->T3122; + if (!wait_ind) + wait_ind = T_def_get(bts->network->T_defs, 3122, T_S, -1); + if (!wait_ind) wait_ind = GSM_T3122_DEFAULT; /* The BTS will gather multiple CHAN RQD and reject up to 4 MS at the same time. */ rsl_send_imm_ass_rej(bts, rqd_ref, wait_ind); @@ -2001,7 +2003,7 @@ static int rsl_send_imm_assignment(struct gsm_lchan *lchan) /* Start timer T3101 to wait for GSM48_MT_RR_PAG_RESP */ osmo_timer_setup(&lchan->T3101, t3101_expired, lchan); - osmo_timer_schedule(&lchan->T3101, bts->network->T3101, 0); + osmo_timer_schedule(&lchan->T3101, T_def_get(bts->network->T_defs, 3101, T_S, -1), 0); /* send IMMEDIATE ASSIGN CMD on RSL to BTS (to send on CCCH to MS) */ return rsl_imm_assign_cmd(bts, sizeof(*ia)+ia->mob_alloc_len, (uint8_t *) ia); @@ -2161,7 +2163,7 @@ static void rsl_handle_release(struct gsm_lchan *lchan) osmo_timer_del(&lchan->T3109); osmo_timer_setup(&lchan->T3111, t3111_expired, lchan); bts = lchan->ts->trx->bts; - osmo_timer_schedule(&lchan->T3111, bts->network->T3111, 0); + osmo_timer_schedule(&lchan->T3111, T_def_get(bts->network->T_defs, 3111, T_S, -1), 0); } /* ESTABLISH INDICATION, LOCATION AREA UPDATE REQUEST @@ -3000,7 +3002,7 @@ int rsl_start_t3109(struct gsm_lchan *lchan) struct gsm_bts *bts = lchan->ts->trx->bts; osmo_timer_setup(&lchan->T3109, t3109_expired, lchan); - osmo_timer_schedule(&lchan->T3109, bts->network->T3109, 0); + osmo_timer_schedule(&lchan->T3109, T_def_get(bts->network->T_defs, 3109, T_S, -1), 0); return 0; } diff --git a/src/osmo-bsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c index 32492707c..f97b7781c 100644 --- a/src/osmo-bsc/bsc_subscr_conn_fsm.c +++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -147,6 +148,25 @@ void bsc_subscr_pick_codec(struct mgcp_conn_peer *conn_peer, struct gsm_subscrib } } +struct state_timeout conn_fsm_timeouts[32] = { + [ST_WAIT_ASS_CMPL] = { .T = 10 }, + [ST_WAIT_CRCX_BTS] = { .T = 992427 }, + [ST_WAIT_MDCX_BTS] = { .T = 992427 }, + [ST_WAIT_CRCX_MSC] = { .T = 992427 }, + [ST_WAIT_MDCX_BTS_HO] = { .T = 992427 }, + [ST_WAIT_CC] = { .T = 993210 }, + [ST_CLEARING] = { .T = 999 }, +}; + +/* Transition to a state, using the T timer defined in conn_fsm_timeouts. + * The actual timeout value is in turn obtained from network->T_defs. + * Assumes local variable 'conn' exists. */ +#define conn_fsm_state_chg(state) \ + fsm_inst_state_chg_T(conn->fi, state, \ + conn_fsm_timeouts, \ + conn->network->T_defs, \ + -1) + /* forward MT DTAP from BSSAP side to RSL side */ static inline void submit_dtap(struct gsm_subscriber_connection *conn, struct msgb *msg, struct osmo_fsm_inst *fi) @@ -324,7 +344,7 @@ static void gscon_fsm_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) } else { /* SCCP T(conn est) is 1-2 minutes, way too long. The MS will timeout * using T3210 (20s), T3220 (5s) or T3230 (10s) */ - osmo_fsm_inst_state_chg(fi, ST_WAIT_CC, 20, 993210); + conn_fsm_state_chg(ST_WAIT_CC); } break; case GSCON_EV_A_CONN_IND: @@ -353,11 +373,12 @@ static void gscon_fsm_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) /* We've sent the CONNECTION.req to the SCCP provider and are waiting for CC from MSC */ static void gscon_fsm_wait_cc(struct osmo_fsm_inst *fi, uint32_t event, void *data) { + struct gsm_subscriber_connection *conn = fi->priv; switch (event) { case GSCON_EV_A_CONN_CFM: /* MSC has confirmed the connection, we now change into the * active state and wait there for further operations */ - osmo_fsm_inst_state_chg(fi, ST_ACTIVE, 0, 0); + conn_fsm_state_chg(ST_ACTIVE); /* if there's user payload, forward it just like EV_MT_DTAP */ /* FIXME: Question: if there's user payload attached to the CC, forward it like EV_MT_DTAP? */ break; @@ -399,7 +420,7 @@ static void _assignment_failed(struct osmo_fsm_inst *fi, enum gsm0808_cause caus resp = gsm0808_create_assignment_failure(cause, NULL); sigtran_send(conn, resp, fi); if (fi->state != ST_ACTIVE) - osmo_fsm_inst_state_chg(fi, ST_ACTIVE, 0, 0); + conn_fsm_state_chg(ST_ACTIVE); } /* We're on an active subscriber connection, passing DTAP back and forth */ @@ -437,7 +458,7 @@ static void gscon_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *dat osmo_strlcpy(conn_peer.endpoint, get_mgw_ep_name(conn), sizeof(conn_peer.endpoint)); /* (Pre)Change state and create the connection */ - osmo_fsm_inst_state_chg(fi, ST_WAIT_CRCX_BTS, MGCP_MGW_TIMEOUT, MGCP_MGW_TIMEOUT_TIMER_NR); + conn_fsm_state_chg(ST_WAIT_CRCX_BTS); conn->user_plane.fi_bts = mgcp_conn_create(conn->network->mgw.client, fi, GSCON_EV_MGW_FAIL_BTS, GSCON_EV_MGW_CRCX_RESP_BTS, &conn_peer); @@ -464,7 +485,7 @@ static void gscon_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *dat return; } - osmo_fsm_inst_state_chg(fi, ST_WAIT_ASS_CMPL, conn->network->T10, 10); + conn_fsm_state_chg(ST_WAIT_ASS_CMPL); break; default: /* An unsupported channel is requested, so we have to @@ -484,7 +505,7 @@ static void gscon_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *dat if (rc) { resp = gsm0808_create_clear_rqst(GSM0808_CAUSE_EQUIPMENT_FAILURE); sigtran_send(conn, resp, fi); - osmo_fsm_inst_state_chg(fi, ST_CLEARING, 0, 0); + conn_fsm_state_chg(ST_CLEARING); return; } @@ -493,7 +514,7 @@ static void gscon_fsm_active(struct osmo_fsm_inst *fi, uint32_t event, void *dat * handover time out, so we do not need another timeout * here (maybe its worth to think about giving GSCON * more power over the actual handover process). */ - osmo_fsm_inst_state_chg(fi, ST_WAIT_HO_COMPL, 0, 0); + conn_fsm_state_chg(ST_WAIT_HO_COMPL); break; case GSCON_EV_A_HO_REQ: /* FIXME: reject any handover requests with HO FAIL until implemented */ @@ -551,7 +572,7 @@ static void gscon_fsm_wait_crcx_bts(struct osmo_fsm_inst *fi, uint32_t event, vo return; } - osmo_fsm_inst_state_chg(fi, ST_WAIT_ASS_CMPL, conn->network->T10, 10); + conn_fsm_state_chg(ST_WAIT_ASS_CMPL); break; case GSCON_EV_MO_DTAP: forward_dtap(conn, (struct msgb *)data, fi); @@ -598,7 +619,7 @@ static void gscon_fsm_wait_ass_cmpl(struct osmo_fsm_inst *fi, uint32_t event, vo conn_peer.ptime = 20; /* (Pre)Change state and modify the connection */ - osmo_fsm_inst_state_chg(fi, ST_WAIT_MDCX_BTS, MGCP_MGW_TIMEOUT, MGCP_MGW_TIMEOUT_TIMER_NR); + conn_fsm_state_chg(ST_WAIT_MDCX_BTS); rc = mgcp_conn_modify(conn->user_plane.fi_bts, GSCON_EV_MGW_MDCX_RESP_BTS, &conn_peer); if (rc != 0) { assignment_failed(fi, GSM0808_CAUSE_EQUIPMENT_FAILURE); @@ -609,7 +630,7 @@ static void gscon_fsm_wait_ass_cmpl(struct osmo_fsm_inst *fi, uint32_t event, vo /* Confirm the successful assignment on BSSMAP and * change back into active state */ send_ass_compl(lchan, fi, false); - osmo_fsm_inst_state_chg(fi, ST_ACTIVE, 0, 0); + conn_fsm_state_chg(ST_ACTIVE); break; default: /* Unsupported modes should have been already filtered @@ -673,12 +694,11 @@ static void gscon_fsm_wait_mdcx_bts(struct osmo_fsm_inst *fi, uint32_t event, vo case OSMO_SS7_ASP_PROT_IPA: /* Send assignment complete message to the MSC */ send_ass_compl(conn->lchan, fi, true); - osmo_fsm_inst_state_chg(fi, ST_ACTIVE, 0, 0); + conn_fsm_state_chg(ST_ACTIVE); break; default: /* (Pre)Change state and create the connection */ - osmo_fsm_inst_state_chg(fi, ST_WAIT_CRCX_MSC, MGCP_MGW_TIMEOUT, - MGCP_MGW_TIMEOUT_TIMER_NR); + conn_fsm_state_chg(ST_WAIT_CRCX_MSC); conn->user_plane.fi_msc = mgcp_conn_create(conn->network->mgw.client, fi, GSCON_EV_MGW_FAIL_MSC, GSCON_EV_MGW_CRCX_RESP_MSC, &conn_peer); @@ -725,7 +745,7 @@ static void gscon_fsm_wait_crcx_msc(struct osmo_fsm_inst *fi, uint32_t event, vo /* Send assignment complete message to the MSC */ send_ass_compl(lchan, fi, true); - osmo_fsm_inst_state_chg(fi, ST_ACTIVE, 0, 0); + conn_fsm_state_chg(ST_ACTIVE); break; case GSCON_EV_MO_DTAP: @@ -790,12 +810,12 @@ static void gscon_fsm_wait_ho_compl(struct osmo_fsm_inst *fi, uint32_t event, vo conn_peer.ptime = 20; /* (Pre)Change state and modify the connection */ - osmo_fsm_inst_state_chg(fi, ST_WAIT_MDCX_BTS_HO, MGCP_MGW_TIMEOUT, MGCP_MGW_HO_TIMEOUT_TIMER_NR); + conn_fsm_state_chg(ST_WAIT_MDCX_BTS_HO); rc = mgcp_conn_modify(conn->user_plane.fi_bts, GSCON_EV_MGW_MDCX_RESP_BTS, &conn_peer); if (rc != 0) { resp = gsm0808_create_clear_rqst(GSM0808_CAUSE_EQUIPMENT_FAILURE); sigtran_send(conn, resp, fi); - osmo_fsm_inst_state_chg(fi, ST_CLEARING, 0, 0); + conn_fsm_state_chg(ST_CLEARING); return; } break; @@ -805,7 +825,7 @@ static void gscon_fsm_wait_ho_compl(struct osmo_fsm_inst *fi, uint32_t event, vo * some reason. This means the phone stays on the TS/BTS on * which it currently is. We will change back to the active * state again as there are no further operations needed */ - osmo_fsm_inst_state_chg(fi, ST_ACTIVE, 0, 0); + conn_fsm_state_chg(ST_ACTIVE); break; default: OSMO_ASSERT(false); @@ -824,7 +844,7 @@ static void gscon_fsm_wait_mdcx_bts_ho(struct osmo_fsm_inst *fi, uint32_t event, /* The MGW has confirmed the handover MDCX, and the handover * is now also done on the RTP side. We may now change back * to the active state. */ - osmo_fsm_inst_state_chg(fi, ST_ACTIVE, 0, 0); + conn_fsm_state_chg(ST_ACTIVE); break; case GSCON_EV_MO_DTAP: forward_dtap(conn, (struct msgb *)data, fi); @@ -955,7 +975,7 @@ static void gscon_fsm_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *d break; case GSCON_EV_A_CLEAR_CMD: /* MSC tells us to cleanly shut down */ - osmo_fsm_inst_state_chg(fi, ST_CLEARING, 0, 0); + conn_fsm_state_chg(ST_CLEARING); gsm0808_clear(conn); /* FIXME: Release all terestrial resources in ST_CLEARING */ /* According to 3GPP 48.008 3.1.9.1. "The BSS need not wait for the radio channel @@ -1080,7 +1100,7 @@ static int gscon_timer_cb(struct osmo_fsm_inst *fi) assignment_failed(fi, GSM0808_CAUSE_EQUIPMENT_FAILURE); break; case MGCP_MGW_HO_TIMEOUT_TIMER_NR: /* Handover failed (no response from MGW) */ - osmo_fsm_inst_state_chg(fi, ST_ACTIVE, 0, 0); + conn_fsm_state_chg(ST_ACTIVE); break; default: OSMO_ASSERT(false); diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c index f25f73106..ababb3eaf 100644 --- a/src/osmo-bsc/bsc_vty.c +++ b/src/osmo-bsc/bsc_vty.c @@ -64,6 +64,7 @@ #include #include #include +#include #include @@ -968,11 +969,6 @@ static int config_write_bts(struct vty *v) return CMD_SUCCESS; } -/* small helper macro for conditional dumping of timer */ -#define VTY_OUT_TIMER(number) \ - if (gsmnet->T##number != GSM_T##number##_DEFAULT) \ - vty_out(vty, " timer t"#number" %u%s", gsmnet->T##number, VTY_NEWLINE) - static int config_write_net(struct vty *vty) { struct gsm_network *gsmnet = gsmnet_from_vty(vty); @@ -993,22 +989,7 @@ static int config_write_net(struct vty *vty) ho_vty_write_net(vty, gsmnet); - VTY_OUT_TIMER(3101); - VTY_OUT_TIMER(3103); - VTY_OUT_TIMER(3105); - VTY_OUT_TIMER(3107); - VTY_OUT_TIMER(3109); - VTY_OUT_TIMER(3111); - VTY_OUT_TIMER(3113); - VTY_OUT_TIMER(3115); - VTY_OUT_TIMER(3117); - VTY_OUT_TIMER(3119); - VTY_OUT_TIMER(3122); - VTY_OUT_TIMER(3141); - VTY_OUT_TIMER(10); - VTY_OUT_TIMER(7); - VTY_OUT_TIMER(8); - VTY_OUT_TIMER(101); + T_defs_vty_write(vty, " "); if (!gsmnet->dyn_ts_allow_tch_f) vty_out(vty, " dyn_ts_allow_tch_f 0%s", VTY_NEWLINE); @@ -1021,11 +1002,8 @@ static int config_write_net(struct vty *vty) vty_out(vty, " timezone %d %d%s", gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE); } - if (gsmnet->t3212 == 0) - vty_out(vty, " no periodic location update%s", VTY_NEWLINE); - else - vty_out(vty, " periodic location update %u%s", - gsmnet->t3212 * 6, VTY_NEWLINE); + + /* writing T3212 from the common T_defs_vty_write() instead. */ { uint16_t meas_port; @@ -1889,48 +1867,6 @@ DEFUN(cfg_net_pag_any_tch, return CMD_SUCCESS; } -#define DEFAULT_TIMER(number) GSM_T##number##_DEFAULT -/* Add another expansion so that DEFAULT_TIMER() becomes its value */ -#define EXPAND_AND_STRINGIFY(x) OSMO_STRINGIFY(x) - -#define DECLARE_TIMER(number, doc) \ - DEFUN(cfg_net_T##number, \ - cfg_net_T##number##_cmd, \ - "timer t" #number " (default|<1-65535>)", \ - "Configure GSM Timers\n" \ - doc " (default: " EXPAND_AND_STRINGIFY(DEFAULT_TIMER(number)) " seconds)\n" \ - "Set to default timer value" \ - " (" EXPAND_AND_STRINGIFY(DEFAULT_TIMER(number)) " seconds)\n" \ - "Timer Value in seconds\n") \ -{ \ - struct gsm_network *gsmnet = gsmnet_from_vty(vty); \ - int value; \ - if (strcmp(argv[0], "default") == 0) \ - value = DEFAULT_TIMER(number); \ - else \ - value = atoi(argv[0]); \ - \ - gsmnet->T##number = value; \ - return CMD_SUCCESS; \ -} - -DECLARE_TIMER(3101, "Set the timeout value for IMMEDIATE ASSIGNMENT") -DECLARE_TIMER(3103, "Set the timeout value for HANDOVER") -DECLARE_TIMER(3105, "Set the timer for repetition of PHYSICAL INFORMATION") -DECLARE_TIMER(3107, "Currently not used") -DECLARE_TIMER(3109, "Set the RSL SACCH deactivation timeout") -DECLARE_TIMER(3111, "Set the RSL timeout to wait before releasing the RF Channel") -DECLARE_TIMER(3113, "Set the time to try paging a subscriber") -DECLARE_TIMER(3115, "Currently not used") -DECLARE_TIMER(3117, "Currently not used") -DECLARE_TIMER(3119, "Currently not used") -DECLARE_TIMER(3122, "Default waiting time (seconds) after IMM ASS REJECT") -DECLARE_TIMER(3141, "Currently not used") -DECLARE_TIMER(10, "Assignment Command timeout in seconds") -DECLARE_TIMER(7, "Set the outgoing inter-BSC Handover timeout, from Handover Required to Handover Command") -DECLARE_TIMER(8, "Set the outgoing inter-BSC Handover timeout, from Handover Command to final Clear") -DECLARE_TIMER(101, "Set the incoming inter-BSC Handover timeout, from Handover Request to Accept") - DEFUN_DEPRECATED(cfg_net_dtx, cfg_net_dtx_cmd, "dtx-used (0|1)", @@ -4734,9 +4670,11 @@ DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd, "Periodic Location Updating Interval in Minutes\n") { struct gsm_network *net = vty->index; + struct T_def *d = T_def_get_entry(net->T_defs, 3212); - net->t3212 = atoi(argv[0]) / 6; - + OSMO_ASSERT(d); + d->val = atoi(argv[0]) / 6; + vty_out(vty, "T%d = %u %s (%s)%s", d->T, d->val, "* 6min", d->desc, VTY_NEWLINE); return CMD_SUCCESS; } @@ -4748,9 +4686,11 @@ DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd, "Periodic Location Updating Interval\n") { struct gsm_network *net = vty->index; + struct T_def *d = T_def_get_entry(net->T_defs, 3212); - net->t3212 = 0; - + OSMO_ASSERT(d); + d->val = 0; + vty_out(vty, "T%d = %u %s (%s)%s", d->T, d->val, "* 6min", d->desc, VTY_NEWLINE); return CMD_SUCCESS; } @@ -4842,23 +4782,9 @@ int bsc_vty_init(struct gsm_network *network) logging_vty_add_cmds(NULL); osmo_talloc_vty_add_cmds(); + T_defs_vty_init(network->T_defs, GSMNET_NODE); + install_element(GSMNET_NODE, &cfg_net_neci_cmd); - install_element(GSMNET_NODE, &cfg_net_T3101_cmd); - install_element(GSMNET_NODE, &cfg_net_T3103_cmd); - install_element(GSMNET_NODE, &cfg_net_T3105_cmd); - install_element(GSMNET_NODE, &cfg_net_T3107_cmd); - install_element(GSMNET_NODE, &cfg_net_T3109_cmd); - install_element(GSMNET_NODE, &cfg_net_T3111_cmd); - install_element(GSMNET_NODE, &cfg_net_T3113_cmd); - install_element(GSMNET_NODE, &cfg_net_T3115_cmd); - install_element(GSMNET_NODE, &cfg_net_T3117_cmd); - install_element(GSMNET_NODE, &cfg_net_T3119_cmd); - install_element(GSMNET_NODE, &cfg_net_T3122_cmd); - install_element(GSMNET_NODE, &cfg_net_T3141_cmd); - install_element(GSMNET_NODE, &cfg_net_T10_cmd); - install_element(GSMNET_NODE, &cfg_net_T7_cmd); - install_element(GSMNET_NODE, &cfg_net_T8_cmd); - install_element(GSMNET_NODE, &cfg_net_T101_cmd); install_element(GSMNET_NODE, &cfg_net_dtx_cmd); install_element(GSMNET_NODE, &cfg_net_pag_any_tch_cmd); /* See also handover commands added on net level from handover_vty.c */ diff --git a/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c b/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c index 1a8d9b07b..d674c1891 100644 --- a/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c +++ b/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.c @@ -23,6 +23,7 @@ #include #include #include +#include static void patch_16(uint8_t *data, const uint16_t val) { @@ -90,7 +91,7 @@ struct msgb *nanobts_attr_bts_get(struct gsm_bts *bts) msgb_tv_fixed_put(msgb, NM_ATT_LDAVG_SLOTS, 2, buf); /* 10 milliseconds */ - msgb_tv_put(msgb, NM_ATT_BTS_AIR_TIMER, bts->network->T3105 > 0? bts->network->T3105 : 13); + msgb_tv_put(msgb, NM_ATT_BTS_AIR_TIMER, T_def_get(bts->network->T_defs, 3105, T_MS, -1)); /* 10 retransmissions of physical config */ msgb_tv_put(msgb, NM_ATT_NY1, 10); diff --git a/src/osmo-bsc/bts_siemens_bs11.c b/src/osmo-bsc/bts_siemens_bs11.c index 2d2351702..1da189fb9 100644 --- a/src/osmo-bsc/bts_siemens_bs11.c +++ b/src/osmo-bsc/bts_siemens_bs11.c @@ -27,6 +27,7 @@ #include #include #include +#include static int bts_model_bs11_start(struct gsm_network *net); @@ -358,7 +359,7 @@ static void patch_nm_tables(struct gsm_bts *bts) uint8_t arfcn_high = (bts->c0->arfcn >> 8) & 0x0f; /* T3105 attribute in units of 10ms */ - bs11_attr_bts[2] = bts->network->T3105 / 10; + bs11_attr_bts[2] = T_def_get(bts->network->T_defs, 3105, T_MS, -1) / 10; /* patch ARFCN into BTS Attributes */ bs11_attr_bts[69] &= 0xf0; diff --git a/src/osmo-bsc/gsm_data.c b/src/osmo-bsc/gsm_data.c index 14a4b5501..e0c1eeb39 100644 --- a/src/osmo-bsc/gsm_data.c +++ b/src/osmo-bsc/gsm_data.c @@ -39,6 +39,7 @@ #include #include #include +#include void *tall_bsc_ctx = NULL; @@ -864,7 +865,7 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, uint8_t bts_num) bts->si_common.chan_desc.att = 1; /* attachment required */ bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5; /* paging frames */ bts->si_common.chan_desc.bs_ag_blks_res = 1; /* reserved AGCH blocks */ - bts->si_common.chan_desc.t3212 = net->t3212; /* Use network's current value */ + bts->si_common.chan_desc.t3212 = T_def_get(net->T_defs, 3212, T_CUSTOM, -1); gsm_bts_set_radio_link_timeout(bts, 32); /* Use RADIO LINK TIMEOUT of 32 */ INIT_LLIST_HEAD(&bts->abis_queue); diff --git a/src/osmo-bsc/gsm_timers.c b/src/osmo-bsc/gsm_timers.c new file mode 100644 index 000000000..cc9bdd906 --- /dev/null +++ b/src/osmo-bsc/gsm_timers.c @@ -0,0 +1,206 @@ +/* Implementation to define Tnnn timers globally and use for FSM state changes. */ +/* (C) 2018 by sysmocom - s.f.m.c. GmbH + * + * Author: Neels Hofmeyr + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include + +#include + +/* a = return_val * b. Return 0 if factor is below 1. */ +static int T_factor(enum T_unit a, enum T_unit b) +{ + if (b == a + || b == T_CUSTOM || a == T_CUSTOM) + return 1; + + switch (b) { + case T_MS: + switch (a) { + case T_S: + return 1000; + case T_M: + return 60*1000; + default: + return 0; + } + case T_S: + switch (a) { + case T_M: + return 60; + default: + return 0; + } + default: + return 0; + } +} + +static int T_round(int val, enum T_unit from_unit, enum T_unit to_unit) +{ + int f; + if (!val) + return 0; + + f = T_factor(from_unit, to_unit); + if (f < 1) { + f = T_factor(to_unit, from_unit); + return (val / f) + (val % f? 1 : 0); + } + return val * f; +} + +/* Return the value of a T timer from a list of T_defs. + * Any value is rounded up to match as_unit: 1100 ms as T_S becomes 2 seconds, as T_M becomes one minute. + * If no such timer is defined, return the default value passed, or abort the program if default < 0. + * + * Usage examples: + * + * - Initialization: + * + * struct T_def global_T_defs[] = { + * { .T=7, .default_val=50, .desc="Water Boiling Timeout" }, // default is .unit=T_S == 0 + * { .T=8, .default_val=300, .desc="Tea brewing" }, + * { .T=9, .default_val=5, .unit=T_M, .desc="Let tea cool down before drinking" }, + * { .T=10, .default_val=20, .unit=T_M, .desc="Forgot to drink tea while it's warm" }, + * {} // <-- important! last entry shall be zero + * }; + * T_defs_reset(global_T_defs); // make all values the default + * T_defs_vty_init(global_T_defs, CONFIG_NODE); + * + * val = T_def_get(global_T_defs, 7, T_S, -1); // -> 50 + * sleep(val); + * + * val = T_def_get(global_T_defs, 7, T_M, -1); // 50 seconds becomes 1 minute -> 1 + * sleep_minutes(val); + * + * val = T_def_get(global_T_defs, 99, T_S, -1); // not defined, program aborts! + * + * val = T_def_get(global_T_defs, 99, T_S, 3); // not defined, returns 3 + */ +int T_def_get(struct T_def *T_defs, int T, enum T_unit as_unit, int val_if_not_present) +{ + struct T_def *d = T_def_get_entry(T_defs, T); + if (!d) { + OSMO_ASSERT(val_if_not_present >= 0); + return val_if_not_present; + } + return T_round(d->val, d->unit, as_unit); +} + +/* Set all T_def values to the default_val. */ +void T_defs_reset(struct T_def *T_defs) +{ + struct T_def *d; + for_each_T_def(d, T_defs) + d->val = d->default_val; +} + +/* Return a pointer to a T_def from an array, or NULL. */ +struct T_def *T_def_get_entry(struct T_def *T_defs, int T) +{ + struct T_def *d; + for_each_T_def(d, T_defs) { + if (d->T == T) + return d; + } + return NULL; +} + +/* Return a state_timeout entry from an array, or return NULL if the entry is zero. + * + * The timeouts_array shall contain exactly 32 elements, which corresponds to the number of states + * allowed by osmo_fsm_*. Lookup is by array index. + * + * For example: + * struct state_timeout my_fsm_timeouts[32] = { + * [MY_FSM_STATE_3] = { .T = 423 }, + * [MY_FSM_STATE_7] = { .T = 235 }, + * [MY_FSM_STATE_8] = { .keep_timer = true }, + * // any state that is omitted will remain zero == no timeout + * }; + * get_state_timeout(MY_FSM_STATE_0, &my_fsm_timeouts) -> NULL, + * get_state_timeout(MY_FSM_STATE_7, &my_fsm_timeouts) -> { .T = 235 } + * + * The intention is then to obtain the timer like T_def_get(global_T_defs, T=235); see also + * fsm_inst_state_chg_T() below. + */ +struct state_timeout *get_state_timeout(uint32_t state, struct state_timeout *timeouts_array) +{ + struct state_timeout *t; + OSMO_ASSERT(state < 32); + t = &timeouts_array[state]; + if (!t->keep_timer && !t->T) + return NULL; + return t; +} + +/* Call osmo_fsm_inst_state_chg() or osmo_fsm_inst_state_chg_keep_timer(), depending on the T value + * defined for this state in the timeouts_array, and obtaining the actual timeout value from T_defs. + * A T timer configured in sub-second precision is rounded up to the next full second. + * + * See get_state_timeout() and T_def_get(). + * + * Should a T number be defined in timeouts_array that is not defined in T_defs, use default_timeout. + * This is best used by wrapping this function call in a macro suitable for a specific FSM + * implementation, which can become as short as: my_fsm_state_chg(fi, NEXT_STATE): + * + * #define my_fsm_state_chg(fi, NEXT_STATE) \ + * fsm_inst_state_chg_T(fi, NEXT_STATE, my_fsm_timeouts, global_T_defs, 5) + * + * my_fsm_state_chg(fi, MY_FSM_STATE_1); + * // -> No timeout configured, will enter state without timeout. + * + * my_fsm_state_chg(fi, MY_FSM_STATE_3); + * // T423 configured for this state, will look up T423 in T_defs, or use 5 seconds if unset. + * + * my_fsm_state_chg(fi, MY_FSM_STATE_8); + * // keep_timer configured for this state, will invoke osmo_fsm_inst_state_chg_keep_timer(). + * + */ +int _fsm_inst_state_chg_T(struct osmo_fsm_inst *fi, uint32_t state, + struct state_timeout *timeouts_array, + struct T_def *T_defs, int default_timeout, + const char *file, int line) +{ + struct state_timeout *t = get_state_timeout(state, timeouts_array); + int val; + + /* No timeout defined for this state? */ + if (!t) + return _osmo_fsm_inst_state_chg(fi, state, 0, 0, file, line); + + if (t->keep_timer) { + int rc = _osmo_fsm_inst_state_chg_keep_timer(fi, state, file, line); + if (t->T && !rc) + fi->T = t->T; + return rc; + } + + val = T_def_get(T_defs, t->T, T_S, default_timeout); + return _osmo_fsm_inst_state_chg(fi, state, val, t->T, file, line); +} + +const struct value_string T_unit_names[] = { + { T_S, "s" }, + { T_MS, "ms" }, + { T_CUSTOM, "(custom)" }, + { 0, NULL } +}; diff --git a/src/osmo-bsc/gsm_timers_vty.c b/src/osmo-bsc/gsm_timers_vty.c new file mode 100644 index 000000000..8a13259ff --- /dev/null +++ b/src/osmo-bsc/gsm_timers_vty.c @@ -0,0 +1,117 @@ +/* Implementation to configure Tnnn timers in VTY */ +/* (C) 2018 by sysmocom - s.f.m.c. GmbH + * + * Author: Neels Hofmeyr + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#include + +#include +#include + +#include + +/* Global singleton list used for the VTY configuration. See T_defs_vty_init(). */ +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) +{ + int T; + struct T_def *d; + + if (T_str[0] == 't' || T_str[0] == 'T') + T_str++; + T = atoi(T_str); + + d = T_def_get_entry(g_vty_T_defs, T); + if (!d) + vty_out(vty, "No such timer: T%d%s", T, VTY_NEWLINE); + return d; +} + +/* Installed in the VTY on T_defs_vty_init(). */ +DEFUN(cfg_timer, cfg_timer_cmd, + "timer TNNNN (default|<1-65535>)", + "Configure GSM Timers\n" + "T-number, optionally preceded by 't' or 'T'." + "See also 'show timer' for a list of available timers.\n" + "Set to default timer value\n" "Timer value\n") +{ + const char *val_str = argv[1]; + struct T_def *d; + + d = parse_T_arg(vty, argv[0]); + if (!d) + return CMD_WARNING; + + if (!strcmp(val_str, "default")) + d->val = d->default_val; + else + d->val = atoi(val_str); + vty_out(vty, "T%d = %u %s (%s)%s", d->T, d->val, T_unit_name(d->unit), d->desc, VTY_NEWLINE); + return CMD_SUCCESS; +} + +/* Print a T_def to the VTY. */ +static void show_one_timer(struct vty *vty, struct T_def *d) +{ + vty_out(vty, "T%d = %u %s (default = %u %s) \t%s%s", + d->T, d->val, T_unit_name(d->unit), + d->default_val, T_unit_name(d->unit), d->desc, VTY_NEWLINE); +} + +/* Installed in the VTY on T_defs_vty_init(). */ +DEFUN(show_timer, show_timer_cmd, + "show timer [TNNNN]", + SHOW_STR "GSM Timers\n" + "Specific timer to show, or all timers if omitted.\n") +{ + struct T_def *d; + + if (argc) { + d = parse_T_arg(vty, argv[0]); + if (!d) + return CMD_WARNING; + show_one_timer(vty, d); + return CMD_SUCCESS; + } + + for_each_T_def(d, g_vty_T_defs) + show_one_timer(vty, d); + return CMD_SUCCESS; +} + +/* Install GSM timer configuration commands in the VTY. */ +void T_defs_vty_init(struct T_def *T_defs, int cfg_parent_node) +{ + install_element_ve(&show_timer_cmd); + install_element(cfg_parent_node, &cfg_timer_cmd); +} + +/* Write GSM timer configuration to the vty. */ +void T_defs_vty_write(struct vty *vty, const char *indent) +{ + struct T_def *d; + for_each_T_def(d, g_vty_T_defs) { + if (d->val != d->default_val) + vty_out(vty, "%stimer t%d %u%s", indent, d->T, d->val, VTY_NEWLINE); + } +} diff --git a/src/osmo-bsc/net_init.c b/src/osmo-bsc/net_init.c index db3d01c1c..4581448ce 100644 --- a/src/osmo-bsc/net_init.c +++ b/src/osmo-bsc/net_init.c @@ -23,6 +23,33 @@ #include #include #include +#include + +static struct T_def gsm_network_T_defs[] = { + { .T=7, .default_val=10, .desc="inter-BSC Handover MO, HO Required to HO Command" }, + { .T=8, .default_val=10, .desc="inter-BSC Handover MO, HO Command to final Clear" }, + { .T=10, .default_val=6, .desc="RR Assignment" }, + { .T=101, .default_val=10, .desc="inter-BSC Handover MT, HO Request to HO Accept" }, + { .T=3101, .default_val=3, .desc="RR Immediate Assignment" }, + { .T=3103, .default_val=5, .desc="Handover" }, + { .T=3105, .default_val=100, .unit=T_MS, .desc="Physical Information" }, + { .T=3107, .default_val=5, .desc="(unused)" }, + { .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=3115, .default_val=10, .desc="(unused)" }, + { .T=3117, .default_val=10, .desc="(unused)" }, + { .T=3119, .default_val=10, .desc="(unused)" }, + { .T=3122, .default_val=GSM_T3122_DEFAULT, .desc="Wait time after RR Immediate Assignment Reject" }, + { .T=3141, .default_val=10, .desc="(unused)" }, + { .T=3212, .default_val=5, .unit=T_CUSTOM, + .desc="Periodic Location Update timer, sent to MS (1 = 6 minutes)" }, + { .T=993210, .default_val=20, .desc="After L3 Complete, wait for MSC to confirm" }, + { .T=999, .default_val=60, .desc="After Clear Request, wait for MSC to Clear Command (sanity)" }, + { .T=992427, .default_val=4, .desc="MGCP timeout (2427 is the default MGCP port number)" }, + {} +}; /* Initialize the bare minimum of struct gsm_network, minimizing required dependencies. * This part is shared among the thin programs in osmo-bsc/src/utils/. @@ -43,9 +70,6 @@ struct gsm_network *gsm_network_init(void *ctx) /* Permit a compile-time default of A5/3 and A5/1 */ net->a5_encryption_mask = (1 << 3) | (1 << 1); - /* Use 30 min periodic update interval as sane default */ - net->t3212 = 5; - INIT_LLIST_HEAD(&net->subscr_conns); net->bsc_subscribers = talloc_zero(net, struct llist_head); @@ -53,22 +77,9 @@ struct gsm_network *gsm_network_init(void *ctx) INIT_LLIST_HEAD(&net->bts_list); net->num_bts = 0; - net->T3101 = GSM_T3101_DEFAULT; - net->T3103 = GSM_T3103_DEFAULT; - net->T3105 = GSM_T3105_DEFAULT; - net->T3107 = GSM_T3107_DEFAULT; - net->T3109 = GSM_T3109_DEFAULT; - net->T3111 = GSM_T3111_DEFAULT; - net->T3113 = GSM_T3113_DEFAULT; - net->T3115 = GSM_T3115_DEFAULT; - net->T3117 = GSM_T3117_DEFAULT; - net->T3119 = GSM_T3119_DEFAULT; - net->T3122 = GSM_T3122_DEFAULT; - net->T3141 = GSM_T3141_DEFAULT; - net->T10 = GSM_T10_DEFAULT; - net->T7 = GSM_T7_DEFAULT; - net->T8 = GSM_T8_DEFAULT; - net->T101 = GSM_T101_DEFAULT; + + net->T_defs = gsm_network_T_defs; + T_defs_reset(net->T_defs); return net; } diff --git a/src/osmo-bsc/paging.c b/src/osmo-bsc/paging.c index feb9fea19..b75d7316b 100644 --- a/src/osmo-bsc/paging.c +++ b/src/osmo-bsc/paging.c @@ -51,6 +51,7 @@ #include #include #include +#include void *tall_paging_ctx = NULL; @@ -315,7 +316,7 @@ 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, bts->network->T3113, 0); + osmo_timer_schedule(&req->T3113, T_def_get(bts->network->T_defs, 3113, T_S, -1), 0); llist_add_tail(&req->entry, &bts_entry->pending_requests); paging_schedule_if_needed(bts_entry); diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am index 543344b53..42118a05c 100644 --- a/src/utils/Makefile.am +++ b/src/utils/Makefile.am @@ -54,6 +54,7 @@ bs11_config_LDADD = \ $(top_builddir)/src/osmo-bsc/bts_siemens_bs11.o \ $(top_builddir)/src/osmo-bsc/e1_config.o \ $(top_builddir)/src/osmo-bsc/gsm_data.o \ + $(top_builddir)/src/osmo-bsc/gsm_timers.o \ $(top_builddir)/src/osmo-bsc/net_init.o \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ @@ -122,6 +123,7 @@ meas_json_SOURCES = \ meas_json_LDADD = \ $(top_builddir)/src/osmo-bsc/gsm_data.o \ + $(top_builddir)/src/osmo-bsc/gsm_timers.o \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOABIS_LIBS) \ diff --git a/tests/abis/Makefile.am b/tests/abis/Makefile.am index 60054d94d..4fc3605c0 100644 --- a/tests/abis/Makefile.am +++ b/tests/abis/Makefile.am @@ -27,6 +27,7 @@ abis_test_SOURCES = \ abis_test_LDADD = \ $(top_builddir)/src/osmo-bsc/abis_nm.o \ $(top_builddir)/src/osmo-bsc/gsm_data.o \ + $(top_builddir)/src/osmo-bsc/gsm_timers.o \ $(top_builddir)/src/osmo-bsc/net_init.o \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOABIS_LIBS) \ diff --git a/tests/bsc/Makefile.am b/tests/bsc/Makefile.am index 2e34d7995..57e883753 100644 --- a/tests/bsc/Makefile.am +++ b/tests/bsc/Makefile.am @@ -43,6 +43,7 @@ bsc_test_LDADD = \ $(top_builddir)/src/osmo-bsc/gsm_04_08_utils.o \ $(top_builddir)/src/osmo-bsc/gsm_04_80_utils.o \ $(top_builddir)/src/osmo-bsc/gsm_data.o \ + $(top_builddir)/src/osmo-bsc/gsm_timers.o \ $(top_builddir)/src/osmo-bsc/handover_cfg.o \ $(top_builddir)/src/osmo-bsc/handover_logic.o \ $(top_builddir)/src/osmo-bsc/neighbor_ident.o \ diff --git a/tests/gsm0408/Makefile.am b/tests/gsm0408/Makefile.am index 3eb47f650..d790fc870 100644 --- a/tests/gsm0408/Makefile.am +++ b/tests/gsm0408/Makefile.am @@ -25,6 +25,7 @@ gsm0408_test_SOURCES = \ gsm0408_test_LDADD = \ $(top_builddir)/src/osmo-bsc/arfcn_range_encode.o \ $(top_builddir)/src/osmo-bsc/gsm_data.o \ + $(top_builddir)/src/osmo-bsc/gsm_timers.o \ $(top_builddir)/src/osmo-bsc/net_init.o \ $(top_builddir)/src/osmo-bsc/rest_octets.o \ $(top_builddir)/src/osmo-bsc/system_information.o \ diff --git a/tests/handover/Makefile.am b/tests/handover/Makefile.am index 140d8ff05..b12b5cb74 100644 --- a/tests/handover/Makefile.am +++ b/tests/handover/Makefile.am @@ -54,6 +54,7 @@ handover_test_LDADD = \ $(top_builddir)/src/osmo-bsc/gsm_04_08_utils.o \ $(top_builddir)/src/osmo-bsc/gsm_04_80_utils.o \ $(top_builddir)/src/osmo-bsc/gsm_data.o \ + $(top_builddir)/src/osmo-bsc/gsm_timers.o \ $(top_builddir)/src/osmo-bsc/handover_cfg.o \ $(top_builddir)/src/osmo-bsc/handover_decision.o \ $(top_builddir)/src/osmo-bsc/handover_decision_2.o \ diff --git a/tests/nanobts_omlattr/Makefile.am b/tests/nanobts_omlattr/Makefile.am index aa7045e49..312cf7d93 100644 --- a/tests/nanobts_omlattr/Makefile.am +++ b/tests/nanobts_omlattr/Makefile.am @@ -26,6 +26,7 @@ nanobts_omlattr_test_LDADD = \ $(top_builddir)/src/osmo-bsc/abis_nm.o \ $(top_builddir)/src/osmo-bsc/bts_ipaccess_nanobts_omlattr.o \ $(top_builddir)/src/osmo-bsc/gsm_data.o \ + $(top_builddir)/src/osmo-bsc/gsm_timers.o \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(LIBOSMOABIS_LIBS) \ diff --git a/tests/nanobts_omlattr/nanobts_omlattr_test.c b/tests/nanobts_omlattr/nanobts_omlattr_test.c index 72dabe542..7a3a80e2d 100644 --- a/tests/nanobts_omlattr/nanobts_omlattr_test.c +++ b/tests/nanobts_omlattr/nanobts_omlattr_test.c @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -191,6 +192,13 @@ static const struct log_info log_info = { .num_cat = ARRAY_SIZE(log_categories), }; +static struct T_def gsm_network_T_defs[] = { + { .T=3105, .default_val=100, .val=13, .unit=T_MS, .desc="Physical Information" }, + { .T=3212, .default_val=5, .unit=T_CUSTOM, + .desc="Periodic Location Update timer, sent to MS (1 = 6 minutes)" }, + {} +}; + int main(int argc, char **argv) { void *ctx; @@ -207,6 +215,7 @@ int main(int argc, char **argv) /* Allocate environmental structs (bts, net, trx) */ net = talloc_zero(ctx, struct gsm_network); INIT_LLIST_HEAD(&net->bts_list); + net->T_defs = gsm_network_T_defs; gsm_bts_model_register(&bts_model_nanobts); bts = gsm_bts_alloc_register(net, GSM_BTS_TYPE_NANOBTS, 63); OSMO_ASSERT(bts); -- cgit v1.2.3