aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/gsm_data.c
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-03-22 03:25:11 +0100
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-03-24 06:16:04 +0100
commit22481bf76d129d3c41d20b96b6587ef085be485b (patch)
tree8c8de852e945dd5422a83bc7e0c37548d2911fe2 /openbsc/src/gsm_data.c
parentb973955295b720b8ba7c556d0165750ed9bfb381 (diff)
parent61b4232c6363ff9d78ef73b9dbf47ec16c94d610 (diff)
Merge remote branch 'origin/master' into on-waves/bsc-master
* Move to libosmocore * Move to new debugging architecture * Register the BTS types * Has only been compile tested Conflicts: openbsc/include/openbsc/Makefile.am openbsc/include/openbsc/gsm_data.h openbsc/include/openbsc/ipaccess.h openbsc/include/openbsc/mgcp.h openbsc/include/openbsc/msgb.h openbsc/include/openbsc/tlv.h openbsc/src/Makefile.am openbsc/src/abis_rsl.c openbsc/src/bsc_init.c openbsc/src/bsc_mgcp.c openbsc/src/chan_alloc.c openbsc/src/debug.c openbsc/src/gsm_subscriber_base.c openbsc/src/msgb.c openbsc/src/rest_octets.c openbsc/src/sccp/sccp.c openbsc/src/vty/command.c openbsc/src/vty_interface.c openbsc/tests/Makefile.am
Diffstat (limited to 'openbsc/src/gsm_data.c')
-rw-r--r--openbsc/src/gsm_data.c195
1 files changed, 139 insertions, 56 deletions
diff --git a/openbsc/src/gsm_data.c b/openbsc/src/gsm_data.c
index 8330b5190..bd331911e 100644
--- a/openbsc/src/gsm_data.c
+++ b/openbsc/src/gsm_data.c
@@ -1,4 +1,4 @@
-/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
+/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -26,23 +26,14 @@
#include <ctype.h>
#include <openbsc/gsm_data.h>
-#include <openbsc/talloc.h>
+#include <osmocore/talloc.h>
+#include <osmocore/gsm_utils.h>
#include <openbsc/abis_nm.h>
+#include <osmocore/statistics.h>
void *tall_bsc_ctx;
-const char *get_value_string(const struct value_string *vs, u_int32_t val)
-{
- int i;
-
- for (i = 0;; i++) {
- if (vs[i].value == 0 && vs[i].str == NULL)
- break;
- if (vs[i].value == val)
- return vs[i].str;
- }
- return "unknown";
-}
+static LLIST_HEAD(bts_models);
void set_ts_e1link(struct gsm_bts_trx_ts *ts, u_int8_t e1_nr,
u_int8_t e1_ts, u_int8_t e1_ts_ss)
@@ -92,7 +83,7 @@ static const char *lchan_names[] = {
[GSM_LCHAN_UNKNOWN] = "UNKNOWN",
};
-const char *gsm_lchan_name(enum gsm_chan_t c)
+const char *gsm_lchant_name(enum gsm_chan_t c)
{
if (c >= ARRAY_SIZE(lchan_names))
return "INVALID";
@@ -100,6 +91,20 @@ const char *gsm_lchan_name(enum gsm_chan_t c)
return lchan_names[c];
}
+static const struct value_string lchan_s_names[] = {
+ { LCHAN_S_NONE, "NONE" },
+ { LCHAN_S_ACT_REQ, "ACTIVATION REQUESTED" },
+ { LCHAN_S_ACTIVE, "ACTIVE" },
+ { LCHAN_S_INACTIVE, "INACTIVE" },
+ { LCHAN_S_REL_REQ, "RELEASE REQUESTED" },
+ { 0, NULL },
+};
+
+const char *gsm_lchans_name(enum gsm_lchan_state s)
+{
+ return get_value_string(lchan_s_names, s);
+}
+
static const char *chreq_names[] = {
[GSM_CHREQ_REASON_EMERG] = "EMERGENCY",
[GSM_CHREQ_REASON_PAG] = "PAGING",
@@ -116,6 +121,29 @@ const char *gsm_chreq_name(enum gsm_chreq_reason_t c)
return chreq_names[c];
}
+static struct gsm_bts_model *bts_model_find(enum gsm_bts_type type)
+{
+ struct gsm_bts_model *model;
+
+ llist_for_each_entry(model, &bts_models, list) {
+ if (model->type == type)
+ return model;
+ }
+
+ return NULL;
+}
+
+int gsm_bts_model_register(struct gsm_bts_model *model)
+{
+ if (bts_model_find(model->type))
+ return -EEXIST;
+
+ tlv_def_patch(&model->nm_att_tlvdef, &nm_att_tlvdef);
+ llist_add_tail(&model->list, &bts_models);
+ return 0;
+}
+
+
struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
{
struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx);
@@ -126,6 +154,7 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
trx->bts = bts;
trx->nr = bts->num_trx++;
+ trx->nm_state.administrative = NM_STATE_UNLOCKED;
for (k = 0; k < TRX_NR_TS; k++) {
struct gsm_bts_trx_ts *ts = &trx->ts[k];
@@ -145,6 +174,9 @@ struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts)
}
}
+ if (trx->nr != 0)
+ trx->nominal_power = bts->c0->nominal_power;
+
llist_add_tail(&trx->list, &bts->trx_list);
return trx;
@@ -154,14 +186,21 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
u_int8_t tsc, u_int8_t bsic)
{
struct gsm_bts *bts = talloc_zero(net, struct gsm_bts);
+ struct gsm_bts_model *model = bts_model_find(type);
int i;
if (!bts)
return NULL;
+ if (!model && type != GSM_BTS_TYPE_UNKNOWN) {
+ talloc_free(bts);
+ return NULL;
+ }
+
bts->network = net;
bts->nr = net->num_bts++;
bts->type = type;
+ bts->model = model;
bts->tsc = tsc;
bts->bsic = bsic;
bts->num_trx = 0;
@@ -175,6 +214,10 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
bts->si_common.cell_alloc.data = bts->si_common.data.cell_alloc;
bts->si_common.cell_alloc.data_len =
sizeof(bts->si_common.data.cell_alloc);
+ bts->si_common.rach_control.re = 1; /* no re-establishment */
+ bts->si_common.rach_control.tx_integer = 9; /* 12 slots spread - 217/115 slots delay */
+ bts->si_common.rach_control.max_trans = 3; /* 7 retransmissions */
+ bts->si_common.rach_control.t2 = 4; /* no emergency calls */
for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
bts->gprs.nsvc[i].bts = bts;
@@ -206,6 +249,7 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c
net->country_code = country_code;
net->network_code = network_code;
net->num_bts = 0;
+ net->reject_cause = GSM48_REJECT_ROAMING_NOT_ALLOWED;
net->T3101 = GSM_T3101_DEFAULT;
net->T3113 = GSM_T3113_DEFAULT;
/* FIXME: initialize all other timers! */
@@ -222,6 +266,32 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c
INIT_LLIST_HEAD(&net->upqueue);
INIT_LLIST_HEAD(&net->bts_list);
+ net->stats.chreq.total = counter_alloc("net.chreq.total");
+ net->stats.chreq.no_channel = counter_alloc("net.chreq.no_channel");
+ net->stats.handover.attempted = counter_alloc("net.handover.attempted");
+ net->stats.handover.no_channel = counter_alloc("net.handover.no_channel");
+ net->stats.handover.timeout = counter_alloc("net.handover.timeout");
+ net->stats.handover.completed = counter_alloc("net.handover.completed");
+ net->stats.handover.failed = counter_alloc("net.handover.failed");
+ net->stats.loc_upd_type.attach = counter_alloc("net.loc_upd_type.attach");
+ net->stats.loc_upd_type.normal = counter_alloc("net.loc_upd_type.normal");
+ net->stats.loc_upd_type.periodic = counter_alloc("net.loc_upd_type.periodic");
+ net->stats.loc_upd_type.detach = counter_alloc("net.imsi_detach.count");
+ net->stats.loc_upd_resp.reject = counter_alloc("net.loc_upd_resp.reject");
+ net->stats.loc_upd_resp.accept = counter_alloc("net.loc_upd_resp.accept");
+ net->stats.paging.attempted = counter_alloc("net.paging.attempted");
+ net->stats.paging.detached = counter_alloc("net.paging.detached");
+ net->stats.paging.completed = counter_alloc("net.paging.completed");
+ net->stats.paging.expired = counter_alloc("net.paging.expired");
+ net->stats.sms.submitted = counter_alloc("net.sms.submitted");
+ net->stats.sms.no_receiver = counter_alloc("net.sms.no_receiver");
+ net->stats.sms.delivered = counter_alloc("net.sms.delivered");
+ net->stats.sms.rp_err_mem = counter_alloc("net.sms.rp_err_mem");
+ net->stats.sms.rp_err_other = counter_alloc("net.sms.rp_err_other");
+ net->stats.call.dialled = counter_alloc("net.call.dialled");
+ net->stats.call.alerted = counter_alloc("net.call.alerted");
+ net->stats.call.connected = counter_alloc("net.call.connected");
+
net->mncc_recv = mncc_recv;
net->core_country_code = -1;
@@ -282,6 +352,15 @@ struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num)
static char ts2str[255];
+char *gsm_trx_name(struct gsm_bts_trx *trx)
+{
+ snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d)",
+ trx->bts->nr, trx->nr);
+
+ return ts2str;
+}
+
+
char *gsm_ts_name(struct gsm_bts_trx_ts *ts)
{
snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d)",
@@ -290,6 +369,16 @@ char *gsm_ts_name(struct gsm_bts_trx_ts *ts)
return ts2str;
}
+char *gsm_lchan_name(struct gsm_lchan *lchan)
+{
+ struct gsm_bts_trx_ts *ts = lchan->ts;
+
+ snprintf(ts2str, sizeof(ts2str), "(bts=%d,trx=%d,ts=%d,ss=%d)",
+ ts->trx->bts->nr, ts->trx->nr, ts->nr, lchan->nr);
+
+ return ts2str;
+}
+
static const char *bts_types[] = {
[GSM_BTS_TYPE_UNKNOWN] = "unknown",
[GSM_BTS_TYPE_BS11] = "bs11",
@@ -313,6 +402,17 @@ const char *btstype2str(enum gsm_bts_type type)
return bts_types[type];
}
+struct gsm_bts_trx *gsm_bts_trx_by_nr(struct gsm_bts *bts, int nr)
+{
+ struct gsm_bts_trx *trx;
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ if (trx->nr == nr)
+ return trx;
+ }
+ return NULL;
+}
+
/* Search for a BTS in the given Location Area; optionally start searching
* with start_bts (for continuing to search after the first result) */
struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
@@ -340,47 +440,6 @@ struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
return NULL;
}
-char *gsm_band_name(enum gsm_band band)
-{
- switch (band) {
- case GSM_BAND_400:
- return "GSM400";
- case GSM_BAND_850:
- return "GSM850";
- case GSM_BAND_900:
- return "GSM900";
- case GSM_BAND_1800:
- return "DCS1800";
- case GSM_BAND_1900:
- return "PCS1900";
- }
- return "invalid";
-}
-
-enum gsm_band gsm_band_parse(const char* mhz)
-{
- while (*mhz && !isdigit(*mhz))
- mhz++;
-
- if (*mhz == '\0')
- return -EINVAL;
-
- switch (atoi(mhz)) {
- case 400:
- return GSM_BAND_400;
- case 850:
- return GSM_BAND_850;
- case 900:
- return GSM_BAND_900;
- case 1800:
- return GSM_BAND_1800;
- case 1900:
- return GSM_BAND_1900;
- default:
- return -EINVAL;
- }
-}
-
static const char *gsm_auth_policy_names[] = {
[GSM_AUTH_POLICY_CLOSED] = "closed",
[GSM_AUTH_POLICY_ACCEPT_ALL] = "accept-all",
@@ -440,3 +499,27 @@ struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
return meas_rep;
}
+
+int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type)
+{
+ struct gsm_bts_model *model;
+
+ model = bts_model_find(type);
+ if (!model)
+ return -EINVAL;
+
+ bts->type = type;
+ bts->model = model;
+
+ switch (bts->type) {
+ case GSM_BTS_TYPE_NANOBTS:
+ /* Set the default OML Stream ID to 0xff */
+ bts->oml_tei = 0xff;
+ bts->c0->nominal_power = 23;
+ break;
+ case GSM_BTS_TYPE_BS11:
+ break;
+ }
+
+ return 0;
+}