diff options
author | Jonathan Santos <jrsantos@jonathanrsantos.com> | 2011-08-17 15:33:57 -0400 |
---|---|---|
committer | Jonathan Santos <jrsantos@jonathanrsantos.com> | 2011-08-17 15:33:57 -0400 |
commit | 5a45b156d4165fed159a290c46676d1383ffcc80 (patch) | |
tree | 3689fb40b5b432140fd48822973b760af93080a6 /src/libcommon | |
parent | 03fd8d014f9871896a86534432c8757d65a576fe (diff) |
New upstream version 0.9.14upstream/0.9.14
Diffstat (limited to 'src/libcommon')
-rw-r--r-- | src/libcommon/Makefile.am | 6 | ||||
-rw-r--r-- | src/libcommon/Makefile.in | 15 | ||||
-rw-r--r-- | src/libcommon/common_vty.c | 13 | ||||
-rw-r--r-- | src/libcommon/debug.c | 6 | ||||
-rw-r--r-- | src/libcommon/gsm_data.c | 398 | ||||
-rw-r--r-- | src/libcommon/gsm_data_shared.c | 478 | ||||
-rw-r--r-- | src/libcommon/socket.c | 21 | ||||
-rw-r--r-- | src/libcommon/talloc_ctx.c | 2 |
8 files changed, 628 insertions, 311 deletions
diff --git a/src/libcommon/Makefile.am b/src/libcommon/Makefile.am index 2895452ea..a832b75c0 100644 --- a/src/libcommon/Makefile.am +++ b/src/libcommon/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) -AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS) -AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS) +AM_CFLAGS=-Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS) +AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS) noinst_LIBRARIES = libcommon.a -libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c socket.c talloc_ctx.c +libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c gsm_data_shared.c socket.c talloc_ctx.c diff --git a/src/libcommon/Makefile.in b/src/libcommon/Makefile.in index 41d52fc6d..c3e417e5d 100644 --- a/src/libcommon/Makefile.in +++ b/src/libcommon/Makefile.in @@ -35,7 +35,7 @@ POST_UNINSTALL = : subdir = src/libcommon DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.in +am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d @@ -54,8 +54,8 @@ am__v_at_0 = @ libcommon_a_AR = $(AR) $(ARFLAGS) libcommon_a_LIBADD = am_libcommon_a_OBJECTS = bsc_version.$(OBJEXT) common_vty.$(OBJEXT) \ - debug.$(OBJEXT) gsm_data.$(OBJEXT) socket.$(OBJEXT) \ - talloc_ctx.$(OBJEXT) + debug.$(OBJEXT) gsm_data.$(OBJEXT) gsm_data_shared.$(OBJEXT) \ + socket.$(OBJEXT) talloc_ctx.$(OBJEXT) libcommon_a_OBJECTS = $(am_libcommon_a_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -112,6 +112,8 @@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBOSMOCORE_CFLAGS = @LIBOSMOCORE_CFLAGS@ LIBOSMOCORE_LIBS = @LIBOSMOCORE_LIBS@ +LIBOSMOGSM_CFLAGS = @LIBOSMOGSM_CFLAGS@ +LIBOSMOGSM_LIBS = @LIBOSMOGSM_LIBS@ LIBOSMOSCCP_CFLAGS = @LIBOSMOSCCP_CFLAGS@ LIBOSMOSCCP_LIBS = @LIBOSMOSCCP_LIBS@ LIBOSMOVTY_CFLAGS = @LIBOSMOVTY_CFLAGS@ @@ -181,10 +183,10 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ INCLUDES = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir) -AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS) -AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(COVERAGE_LDFLAGS) +AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(COVERAGE_CFLAGS) +AM_LDFLAGS = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(COVERAGE_LDFLAGS) noinst_LIBRARIES = libcommon.a -libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c socket.c talloc_ctx.c +libcommon_a_SOURCES = bsc_version.c common_vty.c debug.c gsm_data.c gsm_data_shared.c socket.c talloc_ctx.c all: all-am .SUFFIXES: @@ -237,6 +239,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/common_vty.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_data_shared.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/socket.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/talloc_ctx.Po@am__quote@ diff --git a/src/libcommon/common_vty.c b/src/libcommon/common_vty.c index 84375a22d..5b4b296cb 100644 --- a/src/libcommon/common_vty.c +++ b/src/libcommon/common_vty.c @@ -21,7 +21,7 @@ #include <stdlib.h> #include <string.h> -#include <osmocore/talloc.h> +#include <osmocom/core/talloc.h> #include <openbsc/vty.h> #include <openbsc/gsm_data.h> @@ -83,8 +83,11 @@ enum node_type bsc_vty_go_parent(struct vty *vty) vty->index = bsc_config->nat; } break; + case PGROUP_NODE: + vty->node = NAT_NODE; + break; case MSC_NODE: - vty->node = GSMNET_NODE; + vty->node = CONFIG_NODE; break; case TRUNK_NODE: vty->node = MGCP_NODE; @@ -139,6 +142,9 @@ gDEFUN(ournode_exit, vty->index = bsc_config->nat; } break; + case PGROUP_NODE: + vty->node = NAT_NODE; + break; case MGCP_NODE: case GBPROXY_NODE: case SGSN_NODE: @@ -155,7 +161,7 @@ gDEFUN(ournode_exit, vty->index = NULL; break; case MSC_NODE: - vty->node = GSMNET_NODE; + vty->node = CONFIG_NODE; break; case TRUNK_NODE: vty->node = MGCP_NODE; @@ -189,6 +195,7 @@ gDEFUN(ournode_end, case VTY_NODE: case NAT_NODE: case NAT_BSC_NODE: + case PGROUP_NODE: case MSC_NODE: vty_config_unlock(vty); vty->node = ENABLE_NODE; diff --git a/src/libcommon/debug.c b/src/libcommon/debug.c index ea5db49e5..1372150c8 100644 --- a/src/libcommon/debug.c +++ b/src/libcommon/debug.c @@ -27,9 +27,9 @@ #include <time.h> #include <errno.h> -#include <osmocore/talloc.h> -#include <osmocore/utils.h> -#include <osmocore/logging.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/logging.h> #include <openbsc/gsm_data.h> #include <openbsc/gsm_subscriber.h> #include <openbsc/debug.h> diff --git a/src/libcommon/gsm_data.c b/src/libcommon/gsm_data.c index b2c52e4b1..6b15bd06c 100644 --- a/src/libcommon/gsm_data.c +++ b/src/libcommon/gsm_data.c @@ -26,10 +26,11 @@ #include <netinet/in.h> -#include <osmocore/linuxlist.h> -#include <osmocore/talloc.h> -#include <osmocore/gsm_utils.h> -#include <osmocore/statistics.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/talloc.h> +#include <osmocom/gsm/gsm_utils.h> +#include <osmocom/gsm/abis_nm.h> +#include <osmocom/core/statistics.h> #include <openbsc/gsm_data.h> #include <openbsc/osmo_msc_data.h> @@ -39,80 +40,14 @@ void *tall_bsc_ctx; 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) +void set_ts_e1link(struct gsm_bts_trx_ts *ts, uint8_t e1_nr, + uint8_t e1_ts, uint8_t e1_ts_ss) { ts->e1_link.e1_nr = e1_nr; ts->e1_link.e1_ts = e1_ts; ts->e1_link.e1_ts_ss = e1_ts_ss; } -static const struct value_string pchan_names[] = { - { GSM_PCHAN_NONE, "NONE" }, - { GSM_PCHAN_CCCH, "CCCH" }, - { GSM_PCHAN_CCCH_SDCCH4,"CCCH+SDCCH4" }, - { GSM_PCHAN_TCH_F, "TCH/F" }, - { GSM_PCHAN_TCH_H, "TCH/H" }, - { GSM_PCHAN_SDCCH8_SACCH8C, "SDCCH8" }, - { GSM_PCHAN_PDCH, "PDCH" }, - { GSM_PCHAN_TCH_F_PDCH, "TCH/F_PDCH" }, - { GSM_PCHAN_UNKNOWN, "UNKNOWN" }, - { 0, NULL } -}; - -const char *gsm_pchan_name(enum gsm_phys_chan_config c) -{ - return get_value_string(pchan_names, c); -} - -enum gsm_phys_chan_config gsm_pchan_parse(const char *name) -{ - return get_string_value(pchan_names, name); -} - -static const struct value_string lchant_names[] = { - { GSM_LCHAN_NONE, "NONE" }, - { GSM_LCHAN_SDCCH, "SDCCH" }, - { GSM_LCHAN_TCH_F, "TCH/F" }, - { GSM_LCHAN_TCH_H, "TCH/H" }, - { GSM_LCHAN_UNKNOWN, "UNKNOWN" }, - { 0, NULL } -}; - -const char *gsm_lchant_name(enum gsm_chan_t c) -{ - return get_value_string(lchant_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" }, - { LCHAN_S_REL_ERR, "RELEASE DUE ERROR" }, - { 0, NULL } -}; - -const char *gsm_lchans_name(enum gsm_lchan_state s) -{ - return get_value_string(lchan_s_names, s); -} - -static const struct value_string chreq_names[] = { - { GSM_CHREQ_REASON_EMERG, "EMERGENCY" }, - { GSM_CHREQ_REASON_PAG, "PAGING" }, - { GSM_CHREQ_REASON_CALL, "CALL" }, - { GSM_CHREQ_REASON_LOCATION_UPD,"LOCATION_UPDATE" }, - { GSM_CHREQ_REASON_OTHER, "OTHER" }, - { 0, NULL } -}; - -const char *gsm_chreq_name(enum gsm_chreq_reason_t c) -{ - return get_value_string(chreq_names, c); -} - static struct gsm_bts_model *bts_model_find(enum gsm_bts_type type) { struct gsm_bts_model *model; @@ -130,129 +65,12 @@ 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); + tlv_def_patch(&model->nm_att_tlvdef, &abis_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); - int k; - - if (!trx) - return NULL; - - 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]; - int l; - - ts->trx = trx; - ts->nr = k; - ts->pchan = GSM_PCHAN_NONE; - - ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data); - ts->hopping.arfcns.data = ts->hopping.arfcns_data; - ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data); - ts->hopping.ma.data = ts->hopping.ma_data; - - for (l = 0; l < TS_MAX_LCHAN; l++) { - struct gsm_lchan *lchan; - lchan = &ts->lchan[l]; - - lchan->ts = ts; - lchan->nr = l; - lchan->type = GSM_LCHAN_NONE; - } - } - - if (trx->nr != 0) - trx->nominal_power = bts->c0->nominal_power; - - llist_add_tail(&trx->list, &bts->trx_list); - - return trx; -} - -static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 }; -static const uint8_t bts_cell_timer_default[] = - { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 }; - -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; - INIT_LLIST_HEAD(&bts->trx_list); - bts->ms_max_power = 15; /* dBm */ - - bts->neigh_list_manual_mode = 0; - bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */ - bts->si_common.cell_sel_par.rxlev_acc_min = 0; - bts->si_common.neigh_list.data = bts->si_common.data.neigh_list; - bts->si_common.neigh_list.data_len = - sizeof(bts->si_common.data.neigh_list); - bts->si_common.si5_neigh_list.data = bts->si_common.data.si5_neigh_list; - bts->si_common.si5_neigh_list.data_len = - sizeof(bts->si_common.data.si5_neigh_list); - 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; - bts->gprs.nsvc[i].id = i; - } - memcpy(&bts->gprs.nse.timer, bts_nse_timer_default, - sizeof(bts->gprs.nse.timer)); - memcpy(&bts->gprs.cell.timer, bts_cell_timer_default, - sizeof(bts->gprs.cell.timer)); - - /* create our primary TRX */ - bts->c0 = gsm_bts_trx_alloc(bts); - if (!bts->c0) { - talloc_free(bts); - return NULL; - } - bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4; - - bts->rach_b_thresh = -1; - bts->rach_ldavg_slots = -1; - bts->paging.free_chans_need = -1; - INIT_LLIST_HEAD(&bts->abis_queue); - - llist_add_tail(&bts->list, &net->bts_list); - - return bts; -} - -struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_code, +struct gsm_network *gsm_network_init(uint16_t country_code, uint16_t network_code, int (*mncc_recv)(struct gsm_network *, struct msgb *)) { struct gsm_network *net; @@ -267,6 +85,9 @@ struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_c return NULL; } + /* Init back pointer */ + net->msc_data->network = net; + net->country_code = country_code; net->network_code = network_code; net->num_bts = 0; @@ -287,41 +108,40 @@ 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.mo_setup = counter_alloc("net.call.mo_setup"); - net->stats.call.mo_connect_ack = counter_alloc("net.call.mo_connect_ack"); - net->stats.call.mt_setup = counter_alloc("net.call.mt_setup"); - net->stats.call.mt_connect = counter_alloc("net.call.mt_connect"); - net->stats.chan.rf_fail = counter_alloc("net.chan.rf_fail"); - net->stats.chan.rll_err = counter_alloc("net.chan.rll_err"); - net->stats.bts.oml_fail = counter_alloc("net.bts.oml_fail"); - net->stats.bts.rsl_fail = counter_alloc("net.bts.rsl_fail"); + net->stats.chreq.total = osmo_counter_alloc("net.chreq.total"); + net->stats.chreq.no_channel = osmo_counter_alloc("net.chreq.no_channel"); + net->stats.handover.attempted = osmo_counter_alloc("net.handover.attempted"); + net->stats.handover.no_channel = osmo_counter_alloc("net.handover.no_channel"); + net->stats.handover.timeout = osmo_counter_alloc("net.handover.timeout"); + net->stats.handover.completed = osmo_counter_alloc("net.handover.completed"); + net->stats.handover.failed = osmo_counter_alloc("net.handover.failed"); + net->stats.loc_upd_type.attach = osmo_counter_alloc("net.loc_upd_type.attach"); + net->stats.loc_upd_type.normal = osmo_counter_alloc("net.loc_upd_type.normal"); + net->stats.loc_upd_type.periodic = osmo_counter_alloc("net.loc_upd_type.periodic"); + net->stats.loc_upd_type.detach = osmo_counter_alloc("net.imsi_detach.count"); + net->stats.loc_upd_resp.reject = osmo_counter_alloc("net.loc_upd_resp.reject"); + net->stats.loc_upd_resp.accept = osmo_counter_alloc("net.loc_upd_resp.accept"); + net->stats.paging.attempted = osmo_counter_alloc("net.paging.attempted"); + net->stats.paging.detached = osmo_counter_alloc("net.paging.detached"); + net->stats.paging.completed = osmo_counter_alloc("net.paging.completed"); + net->stats.paging.expired = osmo_counter_alloc("net.paging.expired"); + net->stats.sms.submitted = osmo_counter_alloc("net.sms.submitted"); + net->stats.sms.no_receiver = osmo_counter_alloc("net.sms.no_receiver"); + net->stats.sms.delivered = osmo_counter_alloc("net.sms.delivered"); + net->stats.sms.rp_err_mem = osmo_counter_alloc("net.sms.rp_err_mem"); + net->stats.sms.rp_err_other = osmo_counter_alloc("net.sms.rp_err_other"); + net->stats.call.mo_setup = osmo_counter_alloc("net.call.mo_setup"); + net->stats.call.mo_connect_ack = osmo_counter_alloc("net.call.mo_connect_ack"); + net->stats.call.mt_setup = osmo_counter_alloc("net.call.mt_setup"); + net->stats.call.mt_connect = osmo_counter_alloc("net.call.mt_connect"); + net->stats.chan.rf_fail = osmo_counter_alloc("net.chan.rf_fail"); + net->stats.chan.rll_err = osmo_counter_alloc("net.chan.rll_err"); + net->stats.bts.oml_fail = osmo_counter_alloc("net.bts.oml_fail"); + net->stats.bts.rsl_fail = osmo_counter_alloc("net.bts.rsl_fail"); net->mncc_recv = mncc_recv; - net->msc_data->msc_ip = talloc_strdup(net, "127.0.0.1"); - net->msc_data->msc_port = 5000; + INIT_LLIST_HEAD(&net->msc_data->dests); net->msc_data->ping_timeout = 20; net->msc_data->pong_timeout = 5; net->msc_data->core_ncc = -1; @@ -350,7 +170,7 @@ struct gsm_bts *gsm_bts_num(struct gsm_network *net, int num) /* Get reference to a neighbor cell on a given BCCH ARFCN */ struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts, - u_int16_t arfcn, u_int8_t bsic) + uint16_t arfcn, uint8_t bsic) { struct gsm_bts *neigh; /* FIXME: use some better heuristics here to determine which cell @@ -367,50 +187,6 @@ struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts, return NULL; } -struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num) -{ - struct gsm_bts_trx *trx; - - if (num >= bts->num_trx) - return NULL; - - llist_for_each_entry(trx, &bts->trx_list, list) { - if (trx->nr == num) - return trx; - } - - return NULL; -} - -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)", - ts->trx->bts->nr, ts->trx->nr, ts->nr); - - 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 struct value_string bts_types[] = { { GSM_BTS_TYPE_UNKNOWN, "unknown" }, { GSM_BTS_TYPE_BS11, "bs11" }, @@ -485,23 +261,6 @@ const char *gsm_auth_policy_name(enum gsm_auth_policy policy) return get_value_string(auth_policy_names, policy); } -void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts) -{ - raid->mcc = bts->network->country_code; - raid->mnc = bts->network->network_code; - raid->lac = bts->location_area_code; - raid->rac = bts->gprs.rac; -} - -int gsm48_ra_id_by_bts(u_int8_t *buf, struct gsm_bts *bts) -{ - struct gprs_ra_id raid; - - gprs_ra_id_by_bts(&raid, bts); - - return gsm48_construct_ra(buf, &raid); -} - static const struct value_string rrlp_mode_names[] = { { RRLP_MODE_NONE, "none" }, { RRLP_MODE_MS_BASED, "ms-based" }, @@ -571,6 +330,14 @@ int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type) bts->type = type; bts->model = model; + if (model->start && !model->started) { + int ret = model->start(bts->network); + if (ret < 0) + return ret; + + model->started = true; + } + switch (bts->type) { case GSM_BTS_TYPE_HSL_FEMTO: bts->c0->rsl_tei = 0; @@ -590,3 +357,64 @@ int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type) return 0; } + +struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_type type, + uint8_t tsc, uint8_t bsic) +{ + struct gsm_bts_model *model = bts_model_find(type); + struct gsm_bts *bts; + + if (!model && type != GSM_BTS_TYPE_UNKNOWN) + return NULL; + + bts = gsm_bts_alloc(net); + if (!bts) + return NULL; + + bts->network = net; + bts->nr = net->num_bts++; + bts->type = type; + bts->model = model; + bts->tsc = tsc; + bts->bsic = bsic; + + bts->neigh_list_manual_mode = 0; + bts->si_common.cell_sel_par.cell_resel_hyst = 2; /* 4 dB */ + bts->si_common.cell_sel_par.rxlev_acc_min = 0; + bts->si_common.neigh_list.data = bts->si_common.data.neigh_list; + bts->si_common.neigh_list.data_len = + sizeof(bts->si_common.data.neigh_list); + bts->si_common.si5_neigh_list.data = bts->si_common.data.si5_neigh_list; + bts->si_common.si5_neigh_list.data_len = + sizeof(bts->si_common.data.si5_neigh_list); + 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 */ + + llist_add_tail(&bts->list, &net->bts_list); + + INIT_LLIST_HEAD(&bts->abis_queue); + + return bts; +} + +void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts) +{ + raid->mcc = bts->network->country_code; + raid->mnc = bts->network->network_code; + raid->lac = bts->location_area_code; + raid->rac = bts->gprs.rac; +} + +int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts) +{ + struct gprs_ra_id raid; + + gprs_ra_id_by_bts(&raid, bts); + + return gsm48_construct_ra(buf, &raid); +} diff --git a/src/libcommon/gsm_data_shared.c b/src/libcommon/gsm_data_shared.c new file mode 100644 index 000000000..58e3bed66 --- /dev/null +++ b/src/libcommon/gsm_data_shared.c @@ -0,0 +1,478 @@ +/* (C) 2008-2010 by Harald Welte <laforge@gnumonks.org> + * + * 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 <http://www.gnu.org/licenses/>. + * + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> + +#include <netinet/in.h> + +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/talloc.h> +#include <osmocom/gsm/gsm_utils.h> +#include <osmocom/gsm/abis_nm.h> +#include <osmocom/core/statistics.h> + +#include <openbsc/gsm_data.h> + +void gsm_abis_mo_reset(struct gsm_abis_mo *mo) +{ + mo->nm_state.administrative = NM_STATE_NULL; + mo->nm_state.operational = NM_OPSTATE_NULL; + mo->nm_state.availability = NM_AVSTATE_POWER_OFF; +} + +static void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts, + uint8_t obj_class, uint8_t p1, uint8_t p2, uint8_t p3) +{ + mo->bts = bts; + mo->obj_class = obj_class; + mo->obj_inst.bts_nr = p1; + mo->obj_inst.trx_nr = p2; + mo->obj_inst.ts_nr = p3; + gsm_abis_mo_reset(mo); +} + +static const struct value_string pchan_names[] = { + { GSM_PCHAN_NONE, "NONE" }, + { GSM_PCHAN_CCCH, "CCCH" }, + { GSM_PCHAN_CCCH_SDCCH4,"CCCH+SDCCH4" }, + { GSM_PCHAN_TCH_F, "TCH/F" }, + { GSM_PCHAN_TCH_H, "TCH/H" }, + { GSM_PCHAN_SDCCH8_SACCH8C, "SDCCH8" }, + { GSM_PCHAN_PDCH, "PDCH" }, + { GSM_PCHAN_TCH_F_PDCH, "TCH/F_PDCH" }, + { GSM_PCHAN_UNKNOWN, "UNKNOWN" }, + { 0, NULL } +}; + +const char *gsm_pchan_name(enum gsm_phys_chan_config c) +{ + return get_value_string(pchan_names, c); +} + +enum gsm_phys_chan_config gsm_pchan_parse(const char *name) +{ + return get_string_value(pchan_names, name); +} + +static const struct value_string lchant_names[] = { + { GSM_LCHAN_NONE, "NONE" }, + { GSM_LCHAN_SDCCH, "SDCCH" }, + { GSM_LCHAN_TCH_F, "TCH/F" }, + { GSM_LCHAN_TCH_H, "TCH/H" }, + { GSM_LCHAN_UNKNOWN, "UNKNOWN" }, + { 0, NULL } +}; + +const char *gsm_lchant_name(enum gsm_chan_t c) +{ + return get_value_string(lchant_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" }, + { LCHAN_S_REL_ERR, "RELEASE DUE ERROR" }, + { 0, NULL } +}; + +const char *gsm_lchans_name(enum gsm_lchan_state s) +{ + return get_value_string(lchan_s_names, s); +} + +static const struct value_string chreq_names[] = { + { GSM_CHREQ_REASON_EMERG, "EMERGENCY" }, + { GSM_CHREQ_REASON_PAG, "PAGING" }, + { GSM_CHREQ_REASON_CALL, "CALL" }, + { GSM_CHREQ_REASON_LOCATION_UPD,"LOCATION_UPDATE" }, + { GSM_CHREQ_REASON_OTHER, "OTHER" }, + { 0, NULL } +}; + +const char *gsm_chreq_name(enum gsm_chreq_reason_t c) +{ + return get_value_string(chreq_names, c); +} + +struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts) +{ + struct gsm_bts_trx *trx = talloc_zero(bts, struct gsm_bts_trx); + int k; + + if (!trx) + return NULL; + + trx->bts = bts; + trx->nr = bts->num_trx++; + trx->mo.nm_state.administrative = NM_STATE_UNLOCKED; + + gsm_mo_init(&trx->mo, bts, NM_OC_RADIO_CARRIER, + bts->nr, trx->nr, 0xff); + gsm_mo_init(&trx->bb_transc.mo, bts, NM_OC_BASEB_TRANSC, + bts->nr, trx->nr, 0xff); + + for (k = 0; k < TRX_NR_TS; k++) { + struct gsm_bts_trx_ts *ts = &trx->ts[k]; + int l; + + ts->trx = trx; + ts->nr = k; + ts->pchan = GSM_PCHAN_NONE; + ts->tsc = -1; + + gsm_mo_init(&ts->mo, bts, NM_OC_CHANNEL, + bts->nr, trx->nr, ts->nr); + + ts->hopping.arfcns.data_len = sizeof(ts->hopping.arfcns_data); + ts->hopping.arfcns.data = ts->hopping.arfcns_data; + ts->hopping.ma.data_len = sizeof(ts->hopping.ma_data); + ts->hopping.ma.data = ts->hopping.ma_data; + + for (l = 0; l < TS_MAX_LCHAN; l++) { + struct gsm_lchan *lchan; + lchan = &ts->lchan[l]; + + lchan->ts = ts; + lchan->nr = l; + lchan->type = GSM_LCHAN_NONE; + } + } + + if (trx->nr != 0) + trx->nominal_power = bts->c0->nominal_power; + + llist_add_tail(&trx->list, &bts->trx_list); + + return trx; +} + + +static const uint8_t bts_nse_timer_default[] = { 3, 3, 3, 3, 30, 3, 10 }; +static const uint8_t bts_cell_timer_default[] = + { 3, 3, 3, 3, 3, 10, 3, 10, 3, 10, 3 }; + +struct gsm_bts *gsm_bts_alloc(void *ctx) +{ + struct gsm_bts *bts = talloc_zero(ctx, struct gsm_bts); + int i; + + if (!bts) + return NULL; + + bts->num_trx = 0; + INIT_LLIST_HEAD(&bts->trx_list); + bts->ms_max_power = 15; /* dBm */ + + gsm_mo_init(&bts->mo, bts, NM_OC_BTS, + bts->nr, 0xff, 0xff); + gsm_mo_init(&bts->site_mgr.mo, bts, NM_OC_SITE_MANAGER, + 0xff, 0xff, 0xff); + + for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) { + bts->gprs.nsvc[i].bts = bts; + bts->gprs.nsvc[i].id = i; + gsm_mo_init(&bts->gprs.nsvc[i].mo, bts, NM_OC_GPRS_NSVC, + bts->nr, i, 0xff); + } + memcpy(&bts->gprs.nse.timer, bts_nse_timer_default, + sizeof(bts->gprs.nse.timer)); + gsm_mo_init(&bts->gprs.nse.mo, bts, NM_OC_GPRS_NSE, + bts->nr, 0xff, 0xff); + memcpy(&bts->gprs.cell.timer, bts_cell_timer_default, + sizeof(bts->gprs.cell.timer)); + gsm_mo_init(&bts->gprs.cell.mo, bts, NM_OC_GPRS_CELL, + bts->nr, 0xff, 0xff); + + /* create our primary TRX */ + bts->c0 = gsm_bts_trx_alloc(bts); + if (!bts->c0) { + talloc_free(bts); + return NULL; + } + bts->c0->ts[0].pchan = GSM_PCHAN_CCCH_SDCCH4; + + bts->rach_b_thresh = -1; + bts->rach_ldavg_slots = -1; + bts->paging.free_chans_need = -1; + + return bts; +} + +/* reset the state of all MO in the BTS */ +void gsm_bts_mo_reset(struct gsm_bts *bts) +{ + struct gsm_bts_trx *trx; + unsigned int i; + + gsm_abis_mo_reset(&bts->mo); + gsm_abis_mo_reset(&bts->site_mgr.mo); + for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) + gsm_abis_mo_reset(&bts->gprs.nsvc[i].mo); + gsm_abis_mo_reset(&bts->gprs.nse.mo); + gsm_abis_mo_reset(&bts->gprs.cell.mo); + + llist_for_each_entry(trx, &bts->trx_list, list) { + gsm_abis_mo_reset(&trx->mo); + gsm_abis_mo_reset(&trx->bb_transc.mo); + + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { + struct gsm_bts_trx_ts *ts = &trx->ts[i]; + gsm_abis_mo_reset(&ts->mo); + } + } +} + +struct gsm_bts_trx *gsm_bts_trx_num(struct gsm_bts *bts, int num) +{ + struct gsm_bts_trx *trx; + + if (num >= bts->num_trx) + return NULL; + + llist_for_each_entry(trx, &bts->trx_list, list) { + if (trx->nr == num) + return trx; + } + + return NULL; +} + +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)", + ts->trx->bts->nr, ts->trx->nr, ts->nr); + + 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; +} + +/* obtain the MO structure for a given object instance */ +struct gsm_abis_mo * +gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class, + struct abis_om_obj_inst *obj_inst) +{ + struct gsm_bts_trx *trx; + struct gsm_abis_mo *mo = NULL; + + switch (obj_class) { + case NM_OC_BTS: + mo = &bts->mo; + break; + case NM_OC_RADIO_CARRIER: + if (obj_inst->trx_nr >= bts->num_trx) { + return NULL; + } + trx = gsm_bts_trx_num(bts, obj_inst->trx_nr); + mo = &trx->mo; + break; + case NM_OC_BASEB_TRANSC: + if (obj_inst->trx_nr >= bts->num_trx) { + return NULL; + } + trx = gsm_bts_trx_num(bts, obj_inst->trx_nr); + mo = &trx->bb_transc.mo; + break; + case NM_OC_CHANNEL: + if (obj_inst->trx_nr >= bts->num_trx) { + return NULL; + } + trx = gsm_bts_trx_num(bts, obj_inst->trx_nr); + if (obj_inst->ts_nr >= TRX_NR_TS) + return NULL; + mo = &trx->ts[obj_inst->ts_nr].mo; + break; + case NM_OC_SITE_MANAGER: + mo = &bts->site_mgr.mo; + break; + case NM_OC_BS11: + switch (obj_inst->bts_nr) { + case BS11_OBJ_CCLK: + mo = &bts->bs11.cclk.mo; + break; + case BS11_OBJ_BBSIG: + if (obj_inst->ts_nr > bts->num_trx) + return NULL; + trx = gsm_bts_trx_num(bts, obj_inst->trx_nr); + mo = &trx->bs11.bbsig.mo; + break; + case BS11_OBJ_PA: + if (obj_inst->ts_nr > bts->num_trx) + return NULL; + trx = gsm_bts_trx_num(bts, obj_inst->trx_nr); + mo = &trx->bs11.pa.mo; + break; + default: + return NULL; + } + case NM_OC_BS11_RACK: + mo = &bts->bs11.rack.mo; + break; + case NM_OC_BS11_ENVABTSE: + if (obj_inst->trx_nr >= ARRAY_SIZE(bts->bs11.envabtse)) + return NULL; + mo = &bts->bs11.envabtse[obj_inst->trx_nr].mo; + break; + case NM_OC_GPRS_NSE: + mo = &bts->gprs.nse.mo; + break; + case NM_OC_GPRS_CELL: + mo = &bts->gprs.cell.mo; + break; + case NM_OC_GPRS_NSVC: + if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc)) + return NULL; + mo = &bts->gprs.nsvc[obj_inst->trx_nr].mo; + break; + } + return mo; +} + +/* obtain the gsm_nm_state data structure for a given object instance */ +struct gsm_nm_state * +gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class, + struct abis_om_obj_inst *obj_inst) +{ + struct gsm_abis_mo *mo; + + mo = gsm_objclass2mo(bts, obj_class, obj_inst); + if (!mo) + return NULL; + + return &mo->nm_state; +} + +/* obtain the in-memory data structure of a given object instance */ +void * +gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class, + struct abis_om_obj_inst *obj_inst) +{ + struct gsm_bts_trx *trx; + void *obj = NULL; + + switch (obj_class) { + case NM_OC_BTS: + obj = bts; + break; + case NM_OC_RADIO_CARRIER: + if (obj_inst->trx_nr >= bts->num_trx) { + return NULL; + } + trx = gsm_bts_trx_num(bts, obj_inst->trx_nr); + obj = trx; + break; + case NM_OC_BASEB_TRANSC: + if (obj_inst->trx_nr >= bts->num_trx) { + return NULL; + } + trx = gsm_bts_trx_num(bts, obj_inst->trx_nr); + obj = &trx->bb_transc; + break; + case NM_OC_CHANNEL: + if (obj_inst->trx_nr >= bts->num_trx) { + return NULL; + } + trx = gsm_bts_trx_num(bts, obj_inst->trx_nr); + if (obj_inst->ts_nr >= TRX_NR_TS) + return NULL; + obj = &trx->ts[obj_inst->ts_nr]; + break; + case NM_OC_SITE_MANAGER: + obj = &bts->site_mgr; + break; + case NM_OC_GPRS_NSE: + obj = &bts->gprs.nse; + break; + case NM_OC_GPRS_CELL: + obj = &bts->gprs.cell; + break; + case NM_OC_GPRS_NSVC: + if (obj_inst->trx_nr >= ARRAY_SIZE(bts->gprs.nsvc)) + return NULL; + obj = &bts->gprs.nsvc[obj_inst->trx_nr]; + break; + } + return obj; +} + +/* See Table 10.5.25 of GSM04.08 */ +uint8_t gsm_ts2chan_nr(const struct gsm_bts_trx_ts *ts, uint8_t lchan_nr) +{ + uint8_t cbits, chan_nr; + + switch (ts->pchan) { + case GSM_PCHAN_TCH_F: + case GSM_PCHAN_PDCH: + case GSM_PCHAN_TCH_F_PDCH: + cbits = 0x01; + break; + case GSM_PCHAN_TCH_H: + cbits = 0x02; + cbits += lchan_nr; + break; + case GSM_PCHAN_CCCH_SDCCH4: + cbits = 0x04; + cbits += lchan_nr; + break; + case GSM_PCHAN_SDCCH8_SACCH8C: + cbits = 0x08; + cbits += lchan_nr; + break; + default: + case GSM_PCHAN_CCCH: + cbits = 0x10; + break; + } + + chan_nr = (cbits << 3) | (ts->nr & 0x7); + + return chan_nr; +} + +uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan) +{ + return gsm_ts2chan_nr(lchan->ts, lchan->nr); +} diff --git a/src/libcommon/socket.c b/src/libcommon/socket.c index 47778e746..ff846aa6a 100644 --- a/src/libcommon/socket.c +++ b/src/libcommon/socket.c @@ -28,20 +28,20 @@ #include <string.h> #include <time.h> #include <sys/fcntl.h> -#include <sys/types.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <arpa/inet.h> -#include <osmocore/select.h> -#include <osmocore/tlv.h> -#include <osmocore/msgb.h> +#include <osmocom/core/select.h> +#include <osmocom/gsm/tlv.h> +#include <osmocom/core/msgb.h> #include <openbsc/debug.h> #include <openbsc/gsm_data.h> -#include <osmocore/talloc.h> +#include <osmocom/core/talloc.h> -int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port, - int (*cb)(struct bsc_fd *fd, unsigned int what)) +int make_sock(struct osmo_fd *bfd, int proto, + uint32_t ip, uint16_t port, int priv_nr, + int (*cb)(struct osmo_fd *fd, unsigned int what), void *data) { struct sockaddr_in addr; int ret, on = 1; @@ -64,7 +64,8 @@ int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port, bfd->fd = socket(AF_INET, type, proto); bfd->cb = cb; bfd->when = BSC_FD_READ; - //bfd->data = line; + bfd->data = data; + bfd->priv_nr = priv_nr; if (bfd->fd < 0) { LOGP(DINP, LOGL_ERROR, "could not create socket.\n"); @@ -74,7 +75,7 @@ int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port, memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); - if (ip) + if (ip != INADDR_ANY) addr.sin_addr.s_addr = htonl(ip); else addr.sin_addr.s_addr = INADDR_ANY; @@ -98,7 +99,7 @@ int make_sock(struct bsc_fd *bfd, int proto, u_int32_t ip, u_int16_t port, } } - ret = bsc_register_fd(bfd); + ret = osmo_fd_register(bfd); if (ret < 0) { perror("register_listen_fd"); close(bfd->fd); diff --git a/src/libcommon/talloc_ctx.c b/src/libcommon/talloc_ctx.c index 8e7ec230f..ae6a15636 100644 --- a/src/libcommon/talloc_ctx.c +++ b/src/libcommon/talloc_ctx.c @@ -1,4 +1,4 @@ -#include <osmocore/talloc.h> +#include <osmocom/core/talloc.h> #include <openbsc/gsm_data.h> extern void *tall_msgb_ctx; |