Compare commits

...

9 Commits

Author SHA1 Message Date
Andreas Eversberg
2a2ea42fca Create NS instance at startup time and open/close it at BTS start/stop
The NS instance must be created at startup time before the config is
parsed, so the NS VTY elements will exist at this point. The NS instance
must persist.

Then during BTS start, the NS instance is opened/bound/connected to the
socket that is specified by BTS.

Then during BTS stop, the NS instance is closed, but the NS instance sill
exists.

At PCU stop, the NS instance is completely destroyed.
2013-06-30 10:12:01 +02:00
Andreas Eversberg
65d589bb24 Set debug level for CSN1 to ERROR
This is a workarround. It would be better to:

1. Actually do not save disabled log categories to config

Libosmocore saves all disabled log categories (see config_write_log_single).
This will cause these categories to be enabled after parsing config.

2. Change all CSN1 debug levels to DEBUG.
2013-06-30 09:17:57 +02:00
Andreas Eversberg
047a1a5e39 Add and set NS and BSSGP debugging category at libosmogb 2013-06-30 09:13:34 +02:00
Andreas Eversberg
2d4a477a0f Fix debugging the correct single block allocation frame number 2013-06-30 09:08:31 +02:00
Andreas Eversberg
a004e6a823 Added timing advance support for up and downlink TBFs
The timing advance of any TBF is stored when it ends. Whenever a new TBF
with the same TLLI is created (downlink TBF), the stored TA is recalled.

This algorithm assumes that the mobile does not move too fast during
transfer. Also the mobile must start a connection in order to get correct
initial timing advance.

This algorithm does not implement the timing advance procedure as defined
in TS 04.60. To implement the standard timing advance procedure, the BTS
must decode RACH on certain bursts, the mobile is expected to send them.
This requires much more complexity to a transceiver like USRP/UmTRX or
Calypso BTS.

The algorithm was tested at TA >= 8 and works quite well.
2013-05-13 16:45:21 +02:00
Andreas Eversberg
783aa4bcb8 Allow to enable realtime priority for the BTS process
I ported the Holger's scheduling patch from sysmobts to osmo-pcu.

This is usefull, if PCU uses direct access to the DSP of sysmobts.
The latency to respond to a PH-READY_TO_SEND.ind may not be higher
than 18ms. Currently we are using nice to increase our priority but
for a heavily loaded cell this is not enough. Add an option to enable
realtime scheduling and use it in the screenrc.

Linux offers two realtime scheduling classes these are SCHED_FIFO
and SCHED_RR. For SCHED_FIFO the process is running as long as possible
(potentially taking all the CPU and never yielding it), for SCHED_RR
the process can still be pre-empted at the end of the timeslice.

Using SCHED_RR appears to be the more safe option as a run-a-way
sysmobts process will not be able to take all the CPU time.
2013-05-09 08:58:09 +02:00
Ivan Kluchnikov
b6bb55d88c We shouldn't include the VTY tests in make check by default. 2013-04-24 15:53:25 +04:00
Kat
7dac4862bc Added conditional python-based tests for VTY/config handling 2013-04-06 11:00:20 +02:00
Holger Hans Peter Freyther
72075f0e00 Make the code handle SIGTERM.
This way the pcu can be easily stopped with a sysvinit script.
2013-03-19 18:33:06 +04:00
14 changed files with 290 additions and 31 deletions

2
.gitignore vendored
View File

@@ -20,3 +20,5 @@ ltmain.sh
core
core.*
osmoappdesc.pyc

View File

@@ -1,3 +1,16 @@
AUTOMAKE_OPTIONS = foreign dist-bzip2 1.6
SUBDIRS = src examples
EXTRA_DIST = osmoappdesc.py
if ENABLE_VTY_TESTS
python-tests: $(BUILT_SOURCES)
osmotestvty.py -p $(top_srcdir) -w $(builddir) -v
osmotestconfig.py -p $(top_srcdir) -w $(builddir) -v
else
python-tests: $(BUILT_SOURCES)
@echo "Not running python-based tests (determined at configure-time)"
endif
check-local: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) python-tests

View File

@@ -42,6 +42,21 @@ AC_ARG_ENABLE(sysmocom-dsp,
AC_MSG_RESULT([$enable_sysmocom_dsp])
AM_CONDITIONAL(ENABLE_SYSMODSP, test "x$enable_sysmocom_dsp" = "xyes")
AC_ARG_ENABLE([vty_tests],
AC_HELP_STRING([--enable-vty-tests],
[Include the VTY tests in make check [default=no]]),
[enable_vty_tests="$enableval"],[enable_vty_tests="no"])
if test "x$enable_vty_tests" = "xyes" ; then
AM_PATH_PYTHON
AC_CHECK_PROG(OSMOTESTVTY_CHECK,osmotestvty.py,yes)
if test "x$OSMOTESTVTY_CHECK" != "xyes" ; then
AC_MSG_ERROR([Please install osmocom-python to run the vty tests.])
fi
fi
AC_MSG_CHECKING([whether to enable VTY tests])
AC_MSG_RESULT([$enable_vty_tests])
AM_CONDITIONAL(ENABLE_VTY_TESTS, test "x$enable_vty_tests" = "xyes")
AC_OUTPUT(
src/Makefile
examples/Makefile

26
osmoappdesc.py Normal file
View File

@@ -0,0 +1,26 @@
#!/usr/bin/env python
# (C) 2013 by Katerina Barone-Adesi <kat.obsc@gmail.com>
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU 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 General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
app_configs = {
"osmo-pcu": ["examples/osmo-pcu.cfg"]
}
apps = [(4240, "src/osmo-pcu", "Osmo-PCU", "osmo-pcu"),
]
vty_command = ["src/osmo-pcu", "-c", "examples/osmo-pcu.cfg"]
vty_app = apps[0]

View File

@@ -196,6 +196,7 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
uint8_t trx, ta, ss;
int8_t use_trx;
struct gprs_rlcmac_tbf *old_tbf;
int rc;
/* check for uplink data, so we copy our informations */
tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_UL_TBF);
@@ -207,7 +208,19 @@ int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
old_tbf = tbf;
} else {
use_trx = -1;
ta = 0; /* FIXME: initial TA */
/* we already have an uplink TBF, so we use that TA */
if (tbf)
ta = tbf->ta;
else {
/* recall TA */
rc = recall_timing_advance(tlli);
if (rc < 0) {
LOGP(DRLCMAC, LOGL_NOTICE, "TA unknown"
", assuming 0\n");
ta = 0;
} else
ta = rc;
}
ss = 1; /* PCH assignment only allows one timeslot */
old_tbf = NULL;
}
@@ -455,7 +468,7 @@ int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
return 0;
}
static int sgsn_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, struct msgb *msg, uint16_t bvci)
int sgsn_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, struct msgb *msg, uint16_t bvci)
{
int rc = 0;
switch (event) {
@@ -577,18 +590,11 @@ int gprs_bssgp_create(uint16_t local_port, uint32_t sgsn_ip,
if (bctx)
return 0; /* if already created, must return 0: no error */
bssgp_nsi = gprs_ns_instantiate(&sgsn_ns_cb, tall_pcu_ctx);
if (!bssgp_nsi) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
return -EINVAL;
}
gprs_ns_vty_init(bssgp_nsi);
bssgp_nsi->nsip.local_port = local_port;
rc = gprs_ns_nsip_listen(bssgp_nsi);
if (rc < 0) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create socket\n");
gprs_ns_destroy(bssgp_nsi);
bssgp_nsi = NULL;
gprs_ns_close(bssgp_nsi);
return -EINVAL;
}
@@ -599,17 +605,16 @@ int gprs_bssgp_create(uint16_t local_port, uint32_t sgsn_ip,
nsvc = gprs_ns_nsip_connect(bssgp_nsi, &dest, nsei, nsvci);
if (!nsvc) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSVCt\n");
gprs_ns_destroy(bssgp_nsi);
bssgp_nsi = NULL;
gprs_ns_close(bssgp_nsi);
return -EINVAL;
}
bctx = btsctx_alloc(bvci, nsei);
if (!bctx) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create BSSGP context\n");
gprs_nsvc_delete(nsvc);
nsvc = NULL;
gprs_ns_destroy(bssgp_nsi);
bssgp_nsi = NULL;
gprs_ns_close(bssgp_nsi);
return -EINVAL;
}
bctx->ra_id.mcc = spoof_mcc ? : mcc;
@@ -624,13 +629,12 @@ int gprs_bssgp_create(uint16_t local_port, uint32_t sgsn_ip,
bvc_timer.cb = bvc_timeout;
return 0;
}
void gprs_bssgp_destroy(void)
{
if (!bssgp_nsi)
if (!bctx)
return;
if (osmo_timer_pending(&bvc_timer))
@@ -638,6 +642,7 @@ void gprs_bssgp_destroy(void)
osmo_signal_unregister_handler(SS_L_NS, nsvc_signal_cb, NULL);
gprs_nsvc_delete(nsvc);
nsvc = NULL;
/* FIXME: move this to libgb: btsctx_free() */
@@ -647,7 +652,6 @@ void gprs_bssgp_destroy(void)
/* FIXME: blocking... */
gprs_ns_destroy(bssgp_nsi);
bssgp_nsi = NULL;
gprs_ns_close(bssgp_nsi);
}

View File

@@ -51,6 +51,8 @@ int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struct bssgp
int gprs_bssgp_pcu_rcvmsg(struct msgb *msg);
int sgsn_ns_cb(enum gprs_ns_evt event, struct gprs_nsvc *nsvc, struct msgb *msg, uint16_t bvci);
int gprs_bssgp_create(uint16_t local_port, uint32_t sgsn_ip, uint16_t
sgsn_port, uint16_t nsei, uint16_t nsvci, uint16_t bvci,
uint16_t mcc, uint16_t mnc, uint16_t lac, uint16_t rac,

View File

@@ -33,7 +33,7 @@
/* default categories */
static const struct log_info_cat default_categories[] = {
{"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_INFO, 0},
{"DCSN1", "\033[1;31m", "Concrete Syntax Notation One (CSN1)", LOGL_ERROR, 0},
{"DL1IF", "\033[1;32m", "GPRS PCU L1 interface (L1IF)", LOGL_INFO, 1},
{"DRLCMAC", "\033[0;33m", "GPRS RLC/MAC layer (RLCMAC)", LOGL_NOTICE, 1},
{"DRLCMACDATA", "\033[0;33m", "GPRS RLC/MAC layer Data (RLCMAC)", LOGL_NOTICE, 1},
@@ -41,6 +41,7 @@ static const struct log_info_cat default_categories[] = {
{"DRLCMACUL", "\033[1;36m", "GPRS RLC/MAC layer Uplink (RLCMAC)", LOGL_NOTICE, 1},
{"DRLCMACSCHED", "\033[0;36m", "GPRS RLC/MAC layer Scheduling (RLCMAC)", LOGL_NOTICE, 1},
{"DRLCMACMEAS", "\033[1;31m", "GPRS RLC/MAC layer Measurements (RLCMAC)", LOGL_INFO, 1},
{"DNS","\033[0;34m", "GPRS Network Service (NS)", LOGL_INFO , 1},
{"DBSSGP","\033[1;34m", "GPRS BSS Gateway Protocol (BSSGP)", LOGL_INFO , 1},
{"DPCU", "\033[1;35m", "GPRS Packet Control Unit (PCU)", LOGL_NOTICE, 1},
};

View File

@@ -39,6 +39,7 @@ enum {
DRLCMACUL,
DRLCMACSCHED,
DRLCMACMEAS,
DNS,
DBSSGP,
DPCU,
aDebug_LastEntry

View File

@@ -1819,3 +1819,107 @@ int gprs_rlcmac_paging_request(uint8_t *ptmsi, uint16_t ptmsi_len,
return 0;
}
/*
* timing advance memory
*/
/* enable to debug timing advance memory */
//#define DEBUG_TA
static LLIST_HEAD(gprs_rlcmac_ta_list);
static int gprs_rlcmac_ta_num = 0;
struct gprs_rlcmac_ta {
struct llist_head list;
uint32_t tlli;
uint8_t ta;
};
/* remember timing advance of a given TLLI */
int remember_timing_advance(uint32_t tlli, uint8_t ta)
{
struct gprs_rlcmac_ta *ta_entry;
/* check for existing entry */
llist_for_each_entry(ta_entry, &gprs_rlcmac_ta_list, list) {
if (ta_entry->tlli == tlli) {
#ifdef DEBUG_TA
fprintf(stderr, "update %08x %d\n", tlli, ta);
#endif
ta_entry->ta = ta;
/* relink to end of list */
llist_del(&ta_entry->list);
llist_add_tail(&ta_entry->list, &gprs_rlcmac_ta_list);
return 0;
}
}
#ifdef DEBUG_TA
fprintf(stderr, "remember %08x %d\n", tlli, ta);
#endif
/* if list is full, remove oldest entry */
if (gprs_rlcmac_ta_num == 30) {
ta_entry = llist_entry(gprs_rlcmac_ta_list.next,
struct gprs_rlcmac_ta, list);
llist_del(&ta_entry->list);
talloc_free(ta_entry);
gprs_rlcmac_ta_num--;
}
/* create new TA entry */
ta_entry = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ta);
if (!ta_entry)
return -ENOMEM;
ta_entry->tlli = tlli;
ta_entry->ta = ta;
llist_add_tail(&ta_entry->list, &gprs_rlcmac_ta_list);
gprs_rlcmac_ta_num++;
return 0;
}
int recall_timing_advance(uint32_t tlli)
{
struct gprs_rlcmac_ta *ta_entry;
uint8_t ta;
llist_for_each_entry(ta_entry, &gprs_rlcmac_ta_list, list) {
if (ta_entry->tlli == tlli) {
ta = ta_entry->ta;
#ifdef DEBUG_TA
fprintf(stderr, "recall %08x %d\n", tlli, ta);
#endif
return ta;
}
}
#ifdef DEBUG_TA
fprintf(stderr, "no entry for %08x\n", tlli);
#endif
return -EINVAL;
}
int flush_timing_advance(void)
{
struct gprs_rlcmac_ta *ta_entry;
int count = 0;
while (!llist_empty(&gprs_rlcmac_ta_list)) {
ta_entry = llist_entry(gprs_rlcmac_ta_list.next,
struct gprs_rlcmac_ta, list);
#ifdef DEBUG_TA
fprintf(stderr, "flush entry %08x %d\n", ta_entry->tlli,
ta_entry->ta);
#endif
llist_del(&ta_entry->list);
talloc_free(ta_entry);
count++;
}
gprs_rlcmac_ta_num = 0;
return count;
}

View File

@@ -374,6 +374,8 @@ void tbf_timer_cb(void *_tbf);
int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf);
int gprs_rlcmac_sba_timeout(struct gprs_rlcmac_sba *sba);
int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta);
int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts,
@@ -421,6 +423,12 @@ struct gprs_rlcmac_paging *gprs_rlcmac_dequeue_paging(
struct msgb *gprs_rlcmac_send_packet_paging_request(
struct gprs_rlcmac_pdch *pdch);
int remember_timing_advance(uint32_t tlli, uint8_t ta);
int recall_timing_advance(uint32_t tlli);
int flush_timing_advance(void);
extern "C" {
#endif
int alloc_algorithm_a(struct gprs_rlcmac_tbf *old_tbf,

View File

@@ -206,6 +206,15 @@ int gprs_rlcmac_poll_timeout(struct gprs_rlcmac_tbf *tbf)
return 0;
}
int gprs_rlcmac_sba_timeout(struct gprs_rlcmac_sba *sba)
{
LOGP(DRLCMAC, LOGL_NOTICE, "Poll timeout for SBA\n");
llist_del(&sba->list);
talloc_free(sba);
return 0;
}
static uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap)
{
int i;
@@ -263,6 +272,7 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts,
int8_t tfi = 0; /* must be signed */
uint32_t tlli = 0;
struct gprs_rlcmac_tbf *tbf;
struct gprs_rlcmac_sba *sba;
int rc;
RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)talloc_zero(tall_pcu_ctx, RlcMacUplink_t);
@@ -420,6 +430,7 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts,
if (!tbf) {
uint8_t ms_class = 0;
struct gprs_rlcmac_tbf *dl_tbf;
uint8_t ta;
if ((dl_tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF))) {
LOGP(DRLCMACUL, LOGL_NOTICE, "Got RACH from "
@@ -431,12 +442,28 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts,
LOGP(DRLCMAC, LOGL_DEBUG, "MS requests UL TBF "
"in packet ressource request of single "
"block, so we provide one:\n");
sba = sba_find(trx, ts, fn);
if (!sba) {
LOGP(DRLCMAC, LOGL_NOTICE, "MS requests UL TBF "
"in packet ressource request of single "
"block, but there is no resource request "
"scheduled!\n");
rc = recall_timing_advance(tlli);
if (rc >= 0)
ta = rc;
else
ta = 0;
} else {
ta = sba->ta;
remember_timing_advance(tlli, ta);
llist_del(&sba->list);
talloc_free(sba);
}
if (ul_control_block->u.Packet_Resource_Request.Exist_MS_Radio_Access_capability)
ms_class = get_ms_class_by_capability(&ul_control_block->u.Packet_Resource_Request.MS_Radio_Access_capability);
if (!ms_class)
LOGP(DRLCMAC, LOGL_NOTICE, "MS does not give us a class.\n");
tbf = alloc_ul_tbf(trx, ms_class, tlli, 0, NULL);
#warning FIXME TA!!!
tbf = alloc_ul_tbf(trx, ms_class, tlli, ta, NULL);
if (!tbf)
break;
/* set control ts to current MS's TS, until assignment complete */
@@ -469,6 +496,17 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts,
LOGP(DRLCMAC, LOGL_ERROR, "RX: [PCU <- BTS] %s TFI: %u TLLI: 0x%08x FIXME: Packet ressource request\n", (tbf->direction == GPRS_RLCMAC_UL_TBF) ? "UL" : "DL", tbf->tfi, tbf->tlli);
break;
case MT_PACKET_MEASUREMENT_REPORT:
sba = sba_find(trx, ts, fn);
if (!sba) {
LOGP(DRLCMAC, LOGL_NOTICE, "MS send measurement "
"in packet ressource request of single "
"block, but there is no resource request "
"scheduled!\n");
} else {
remember_timing_advance(ul_control_block->u.Packet_Measurement_Report.TLLI, sba->ta);
llist_del(&sba->list);
talloc_free(sba);
}
gprs_rlcmac_meas_rep(&ul_control_block->u.Packet_Measurement_Report);
break;
default:
@@ -888,6 +926,8 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts,
}
/* mark TLLI valid now */
tbf->tlli_valid = 1;
/* store current timing advance */
remember_timing_advance(tbf->tlli, tbf->ta);
/* already have TLLI, but we stille get another one */
} else if (rh->ti) {
uint32_t tlli;

View File

@@ -78,11 +78,8 @@ uint32_t sched_sba(uint8_t trx, uint8_t ts, uint32_t fn, uint8_t block_nr)
sba_fn ++;
sba_fn = sba_fn % 2715648;
sba = sba_find(trx, ts, sba_fn);
if (sba) {
llist_del(&sba->list);
talloc_free(sba);
if (sba)
return sba_fn;
}
return 0xffffffff;
}
@@ -260,7 +257,7 @@ int gprs_rlcmac_rcv_rts_block(uint8_t trx, uint8_t ts, uint16_t arfcn,
? "UL" : "DL", poll_tbf->tfi);
/* use free USF */
/* else. check for sba */
else if ((sba_fn = sched_sba(trx, ts, fn, block_nr) != 0xffffffff))
else if ((sba_fn = sched_sba(trx, ts, fn, block_nr)) != 0xffffffff)
LOGP(DRLCMACSCHED, LOGL_DEBUG, "Received RTS for PDCH: TRX=%d "
"TS=%d FN=%d block_nr=%d scheduling free USF for "
"single block allocation at FN=%d\n", trx, ts, fn,

View File

@@ -516,6 +516,7 @@ bssgp_failed:
static int pcu_rx_time_ind(struct gsm_pcu_if_time_ind *time_ind)
{
struct gprs_rlcmac_tbf *tbf;
struct gprs_rlcmac_sba *sba, *sba2;
uint32_t elapsed;
uint8_t fn13 = time_ind->fn % 13;
@@ -531,18 +532,27 @@ static int pcu_rx_time_ind(struct gsm_pcu_if_time_ind *time_ind)
/* check for poll timeout */
llist_for_each_entry(tbf, &gprs_rlcmac_ul_tbfs, list) {
if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) {
elapsed = (frame_number - tbf->poll_fn) % 2715648;
if (elapsed >= 20 && elapsed < 200)
elapsed = (frame_number + 2715648 - tbf->poll_fn)
% 2715648;
if (elapsed >= 20 && elapsed < 2715400)
gprs_rlcmac_poll_timeout(tbf);
}
}
llist_for_each_entry(tbf, &gprs_rlcmac_dl_tbfs, list) {
if (tbf->poll_state == GPRS_RLCMAC_POLL_SCHED) {
elapsed = (frame_number - tbf->poll_fn) % 2715648;
if (elapsed >= 20 && elapsed < 200)
elapsed = (frame_number + 2715648 - tbf->poll_fn)
% 2715648;
if (elapsed >= 20 && elapsed < 2715400)
gprs_rlcmac_poll_timeout(tbf);
}
}
llist_for_each_entry_safe(sba, sba2, &gprs_rlcmac_sbas, list) {
elapsed = (frame_number + 2715648 - sba->fn) % 2715648;
if (elapsed >= 20 && elapsed < 2715400) {
/* sba will be freed here */
gprs_rlcmac_sba_timeout(sba);
}
}
return 0;
}

View File

@@ -26,6 +26,7 @@
#include <unistd.h>
#include <getopt.h>
#include <signal.h>
#include <sched.h>
extern "C" {
#include "pcu_vty.h"
#include <osmocom/vty/telnet_interface.h>
@@ -41,6 +42,7 @@ extern struct vty_app_info pcu_vty_info;
void *tall_pcu_ctx;
extern void *bv_tall_ctx;
static int quit = 0;
static int rt_prio = -1;
#ifdef DEBUG_DIAGRAM
extern struct timeval diagram_time;
@@ -56,6 +58,8 @@ static void print_help()
"provided by BTS\n"
" -n --mnc MNC use given MNC instead of value "
"provided by BTS\n"
" -r --realtime PRIO Use SCHED_RR with the specified "
"priority\n"
);
}
@@ -70,10 +74,11 @@ static void handle_options(int argc, char **argv)
{ "mcc", 1, 0, 'm' },
{ "mnc", 1, 0, 'n' },
{ "version", 0, 0, 'V' },
{ "realtime", 1, 0, 'r' },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "hc:m:n:V",
c = getopt_long(argc, argv, "hc:m:n:Vr:",
long_options, &option_idx);
if (c == -1)
break;
@@ -97,6 +102,9 @@ static void handle_options(int argc, char **argv)
print_version(1);
exit(0);
break;
case 'r':
rt_prio = atoi(optarg);
break;
default:
fprintf(stderr, "Unknown option '%c'\n", c);
exit(0);
@@ -114,6 +122,7 @@ void sighandler(int sigset)
switch (sigset) {
case SIGINT:
case SIGTERM:
/* If another signal is received afterwards, the program
* is terminated without finishing shutdown process.
*/
@@ -140,6 +149,7 @@ void sighandler(int sigset)
int main(int argc, char *argv[])
{
struct sched_param param;
struct gprs_rlcmac_bts *bts;
int rc;
@@ -168,10 +178,19 @@ int main(int argc, char *argv[])
msgb_set_talloc_ctx(tall_pcu_ctx);
osmo_init_logging(&gprs_log_info);
bssgp_set_log_ss(DBSSGP);
gprs_ns_set_log_ss(DNS);
vty_init(&pcu_vty_info);
pcu_vty_init(&gprs_log_info);
bssgp_nsi = gprs_ns_instantiate(&sgsn_ns_cb, tall_pcu_ctx);
if (!bssgp_nsi) {
LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n");
return -EINVAL;
}
gprs_ns_vty_init(bssgp_nsi);
handle_options(argc, argv);
if ((!!spoof_mcc) + (!!spoof_mnc) == 1) {
fprintf(stderr, "--mcc and --mnc must be specified "
@@ -211,6 +230,18 @@ int main(int argc, char *argv[])
signal(SIGUSR1, sighandler);
signal(SIGUSR2, sighandler);
/* enable realtime priority for us */
if (rt_prio != -1) {
memset(&param, 0, sizeof(param));
param.sched_priority = rt_prio;
rc = sched_setscheduler(getpid(), SCHED_RR, &param);
if (rc != 0) {
fprintf(stderr, "Setting SCHED_RR priority(%d) failed: %s\n",
param.sched_priority, strerror(errno));
exit(1);
}
}
while (!quit) {
osmo_gsm_timers_check();
osmo_gsm_timers_prepare();
@@ -226,6 +257,11 @@ int main(int argc, char *argv[])
pcu_l1if_close();
gprs_ns_destroy(bssgp_nsi);
bssgp_nsi = NULL;
flush_timing_advance();
talloc_free(gprs_rlcmac_bts);
talloc_report_full(tall_pcu_ctx, stderr);