mirror of
				https://gitea.osmocom.org/cellular-infrastructure/osmo-pcu.git
				synced 2025-11-04 06:03:30 +00:00 
			
		
		
		
	Compare commits
	
		
			9 Commits
		
	
	
		
			zecke/hack
			...
			jolly/test
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2a2ea42fca | ||
| 
						 | 
					65d589bb24 | ||
| 
						 | 
					047a1a5e39 | ||
| 
						 | 
					2d4a477a0f | ||
| 
						 | 
					a004e6a823 | ||
| 
						 | 
					783aa4bcb8 | ||
| 
						 | 
					b6bb55d88c | ||
| 
						 | 
					7dac4862bc | ||
| 
						 | 
					72075f0e00 | 
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -20,3 +20,5 @@ ltmain.sh
 | 
			
		||||
 | 
			
		||||
core
 | 
			
		||||
core.*
 | 
			
		||||
 | 
			
		||||
osmoappdesc.pyc
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								Makefile.am
									
									
									
									
									
								
							@@ -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
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								configure.ac
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								configure.ac
									
									
									
									
									
								
							@@ -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
									
								
							
							
						
						
									
										26
									
								
								osmoappdesc.py
									
									
									
									
									
										Normal 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]
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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},
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@ enum {
 | 
			
		||||
	DRLCMACUL,
 | 
			
		||||
	DRLCMACSCHED,
 | 
			
		||||
	DRLCMACMEAS,
 | 
			
		||||
	DNS,
 | 
			
		||||
	DBSSGP,
 | 
			
		||||
	DPCU,
 | 
			
		||||
	aDebug_LastEntry
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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,
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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(¶m, 0, sizeof(param));
 | 
			
		||||
		param.sched_priority = rt_prio;
 | 
			
		||||
		rc = sched_setscheduler(getpid(), SCHED_RR, ¶m);
 | 
			
		||||
		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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user