[PATCH 1/8] tbf: Begin to add some structure to the tbf code

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/osmocom-net-gprs@lists.osmocom.org/.

Holger Freyther hfreyther at sysmocom.de
Wed Oct 16 14:23:41 UTC 2013


From: Holger Hans Peter Freyther <holger at moiji-mobile.com>

The TBF should use the IMSI to identify a block flow but all
handling is spread across the entire code. Start to clean this
up by moving relevant code into the tbf file. Afterwards one
can clean up and add more internal structure.
---
 src/Makefile.am        |   6 +-
 src/gprs_bssgp_pcu.cpp | 121 +------------------------------------
 src/tbf.cpp            | 160 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/tbf.h              |  27 +++++++++
 4 files changed, 194 insertions(+), 120 deletions(-)
 create mode 100644 src/tbf.cpp
 create mode 100644 src/tbf.h

diff --git a/src/Makefile.am b/src/Makefile.am
index 38a4b3c..6646f53 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -40,7 +40,8 @@ libgprs_la_SOURCES = \
 	gsm_timer.cpp \
 	bitvector.cpp \
 	pcu_l1_if.cpp \
-	pcu_vty.c
+	pcu_vty.c \
+	tbf.cpp
 
 if ENABLE_SYSMOBTS
 libgprs_la_SOURCES += \
@@ -72,7 +73,8 @@ noinst_HEADERS = \
 	bitvector.h \
 	pcu_vty.h \
 	sysmo_l1_if.h \
-	femtobts.h
+	femtobts.h \
+	tbf.h
 
 osmo_pcu_SOURCES = pcu_main.cpp
 
diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp
index 4833af8..3432bca 100644
--- a/src/gprs_bssgp_pcu.cpp
+++ b/src/gprs_bssgp_pcu.cpp
@@ -21,6 +21,7 @@
 #include <gprs_rlcmac.h>
 #include <gprs_bssgp_pcu.h>
 #include <pcu_l1_if.h>
+#include <tbf.h>
 
 static struct gprs_bssgp_pcu the_pcu = { 0, };
 
@@ -103,12 +104,9 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
 {
 	struct bssgp_ud_hdr *budh;
 
-	int8_t tfi; /* must be signed */
-
 	uint32_t tlli;
 	uint8_t *data;
 	uint16_t len;
-	struct gprs_rlcmac_tbf *tbf;
 	char imsi[16] = "000";
 
 	budh = (struct bssgp_ud_hdr *)msgb_bssgph(msg);
@@ -123,7 +121,7 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
 
 	data = (uint8_t *) TLVP_VAL(tp, BSSGP_IE_LLC_PDU);
 	len = TLVP_LEN(tp, BSSGP_IE_LLC_PDU);
-	if (len > sizeof(tbf->llc_frame))
+	if (len > sizeof(gprs_rlcmac_tbf::llc_frame))
 	{
 		LOGP(DBSSGP, LOGL_NOTICE, "BSSGP TLLI=0x%08x Rx UL-UD IE_LLC_PDU too large\n", tlli);
 		return bssgp_tx_status(BSSGP_CAUSE_COND_IE_ERR, NULL, msg);
@@ -154,120 +152,7 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp)
 
 	LOGP(DBSSGP, LOGL_INFO, "LLC [SGSN -> PCU] = TLLI: 0x%08x IMSI: %s len: %d\n", tlli, imsi, len);
 
-	/* check for existing TBF */
-	if ((tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF))) {
-		LOGP(DRLCMAC, LOGL_INFO, "TBF: APPEND TFI: %u TLLI: 0x%08x\n", tbf->tfi, tbf->tlli);
-		if (tbf->state == GPRS_RLCMAC_WAIT_RELEASE) {
-			LOGP(DRLCMAC, LOGL_DEBUG, "TBF in WAIT RELEASE state "
-				"(T3193), so reuse TBF\n");
-			memcpy(tbf->llc_frame, data, len);
-			tbf->llc_length = len;
-			memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl)); /* reset
-								rlc states */
-			tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep
-				to flags */
-			tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
-			if (!tbf->ms_class && ms_class)
-				tbf->ms_class = ms_class;
-			tbf_update(tbf);
-			gprs_rlcmac_trigger_downlink_assignment(tbf, tbf, NULL);
-		} else {
-			/* the TBF exists, so we must write it in the queue
-			 * we prepend lifetime in front of PDU */
-			struct timeval *tv;
-			struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv),
-				"llc_pdu_queue");
-			if (!llc_msg)
-				return -ENOMEM;
-			tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
-			if (the_pcu.bts->force_llc_lifetime)
-				delay_csec = the_pcu.bts->force_llc_lifetime;
-			/* keep timestap at 0 for infinite delay */
-			if (delay_csec != 0xffff) {
-				/* calculate timestamp of timeout */
-				gettimeofday(tv, NULL);
-				tv->tv_usec += (delay_csec % 100) * 10000;
-				tv->tv_sec += delay_csec / 100;
-				if (tv->tv_usec > 999999) {
-					tv->tv_usec -= 1000000;
-					tv->tv_sec++;
-				}
-			}
-			memcpy(msgb_put(llc_msg, len), data, len);
-			msgb_enqueue(&tbf->llc_queue, llc_msg);
-			/* set ms class for updating TBF */
-			if (!tbf->ms_class && ms_class)
-				tbf->ms_class = ms_class;
-		}
-	} else {
-		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);
-		if (tbf && tbf->dir.ul.contention_resolution_done
-		 && !tbf->dir.ul.final_ack_sent) {
-			use_trx = tbf->trx;
-			ta = tbf->ta;
-			ss = 0;
-			old_tbf = tbf;
-		} else {
-			use_trx = -1;
-			/* 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;
-		}
-
-		// Create new TBF (any TRX)
-		tfi = tfi_find_free(the_pcu.bts, GPRS_RLCMAC_DL_TBF, &trx, use_trx);
-		if (tfi < 0) {
-			LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
-			/* FIXME: send reject */
-			return -EBUSY;
-		}
-		/* set number of downlink slots according to multislot class */
-		tbf = tbf_alloc(the_pcu.bts, tbf, GPRS_RLCMAC_DL_TBF, tfi, trx, ms_class,
-			ss);
-		if (!tbf) {
-			LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
-			/* FIXME: send reject */
-			return -EBUSY;
-		}
-		tbf->tlli = tlli;
-		tbf->tlli_valid = 1;
-		tbf->ta = ta;
-
-		LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [DOWNLINK] START TFI: %d TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
-
-		/* new TBF, so put first frame */
-		memcpy(tbf->llc_frame, data, len);
-		tbf->llc_length = len;
-
-		/* trigger downlink assignment and set state to ASSIGN.
-		 * we don't use old_downlink, so the possible uplink is used
-		 * to trigger downlink assignment. if there is no uplink,
-		 * AGCH is used. */
-		gprs_rlcmac_trigger_downlink_assignment(tbf, old_tbf, imsi);
-	}
-
-	/* store IMSI for debugging purpose */
-	strncpy(tbf->meas.imsi, imsi, sizeof(tbf->meas.imsi) - 1);
-
-	return 0;
+	return tbf_handle(the_pcu.bts, tlli, imsi, ms_class, delay_csec, data, len);
 }
 
 int gprs_bssgp_pcu_rx_paging_ps(struct msgb *msg, struct tlv_parsed *tp)
diff --git a/src/tbf.cpp b/src/tbf.cpp
new file mode 100644
index 0000000..816fdb8
--- /dev/null
+++ b/src/tbf.cpp
@@ -0,0 +1,160 @@
+/* Copied from gprs_bssgp_pcu.cpp
+ *
+ * Copyright (C) 2012 Ivan Klyuchnikov
+ * Copyright (C) 2013 by Holger Hans Peter Freyther
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <tbf.h>
+#include <gprs_rlcmac.h>
+#include <gprs_debug.h>
+
+extern "C" {
+#include <osmocom/core/msgb.h>
+}
+
+#include <errno.h>
+#include <string.h>
+
+/**
+ * TODO: split into unit test-able parts...
+ */
+int tbf_handle(struct gprs_rlcmac_bts *bts,
+		const uint32_t tlli, const char *imsi,
+		const uint8_t ms_class, const uint16_t pdu_delay_csec,
+		const uint8_t *data, const uint16_t len)
+{
+	struct gprs_rlcmac_tbf *tbf;
+	int8_t tfi; /* must be signed */
+
+	/* check for existing TBF */
+	if ((tbf = tbf_by_tlli(tlli, GPRS_RLCMAC_DL_TBF))) {
+		LOGP(DRLCMAC, LOGL_INFO, "TBF: APPEND TFI: %u TLLI: 0x%08x\n", tbf->tfi, tbf->tlli);
+		if (tbf->state == GPRS_RLCMAC_WAIT_RELEASE) {
+			LOGP(DRLCMAC, LOGL_DEBUG, "TBF in WAIT RELEASE state "
+				"(T3193), so reuse TBF\n");
+			memcpy(tbf->llc_frame, data, len);
+			tbf->llc_length = len;
+			memset(&tbf->dir.dl, 0, sizeof(tbf->dir.dl)); /* reset
+								rlc states */
+			tbf->state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; /* keep
+				to flags */
+			tbf->state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH);
+			if (!tbf->ms_class && ms_class)
+				tbf->ms_class = ms_class;
+			tbf_update(tbf);
+			gprs_rlcmac_trigger_downlink_assignment(tbf, tbf, NULL);
+		} else {
+			/* the TBF exists, so we must write it in the queue
+			 * we prepend lifetime in front of PDU */
+			struct timeval *tv;
+			struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv),
+				"llc_pdu_queue");
+			if (!llc_msg)
+				return -ENOMEM;
+			tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv));
+
+			uint16_t delay_csec;
+			if (bts->force_llc_lifetime)
+				delay_csec = bts->force_llc_lifetime;
+			else
+				delay_csec = pdu_delay_csec;
+			/* keep timestap at 0 for infinite delay */
+			if (delay_csec != 0xffff) {
+				/* calculate timestamp of timeout */
+				gettimeofday(tv, NULL);
+				tv->tv_usec += (delay_csec % 100) * 10000;
+				tv->tv_sec += delay_csec / 100;
+				if (tv->tv_usec > 999999) {
+					tv->tv_usec -= 1000000;
+					tv->tv_sec++;
+				}
+			}
+			memcpy(msgb_put(llc_msg, len), data, len);
+			msgb_enqueue(&tbf->llc_queue, llc_msg);
+			/* set ms class for updating TBF */
+			if (!tbf->ms_class && ms_class)
+				tbf->ms_class = ms_class;
+		}
+	} else {
+		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);
+		if (tbf && tbf->dir.ul.contention_resolution_done
+		 && !tbf->dir.ul.final_ack_sent) {
+			use_trx = tbf->trx;
+			ta = tbf->ta;
+			ss = 0;
+			old_tbf = tbf;
+		} else {
+			use_trx = -1;
+			/* 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;
+		}
+
+		// Create new TBF (any TRX)
+		tfi = tfi_find_free(bts, GPRS_RLCMAC_DL_TBF, &trx, use_trx);
+		if (tfi < 0) {
+			LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n");
+			/* FIXME: send reject */
+			return -EBUSY;
+		}
+		/* set number of downlink slots according to multislot class */
+		tbf = tbf_alloc(bts, tbf, GPRS_RLCMAC_DL_TBF, tfi, trx, ms_class,
+			ss);
+		if (!tbf) {
+			LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n");
+			/* FIXME: send reject */
+			return -EBUSY;
+		}
+		tbf->tlli = tlli;
+		tbf->tlli_valid = 1;
+		tbf->ta = ta;
+
+		LOGP(DRLCMAC, LOGL_DEBUG, "TBF: [DOWNLINK] START TFI: %d TLLI: 0x%08x \n", tbf->tfi, tbf->tlli);
+
+		/* new TBF, so put first frame */
+		memcpy(tbf->llc_frame, data, len);
+		tbf->llc_length = len;
+
+		/* trigger downlink assignment and set state to ASSIGN.
+		 * we don't use old_downlink, so the possible uplink is used
+		 * to trigger downlink assignment. if there is no uplink,
+		 * AGCH is used. */
+		gprs_rlcmac_trigger_downlink_assignment(tbf, old_tbf, imsi);
+	}
+
+	/* store IMSI for debugging purpose */
+	strncpy(tbf->meas.imsi, imsi, sizeof(tbf->meas.imsi) - 1);
+	return 0;
+}
diff --git a/src/tbf.h b/src/tbf.h
new file mode 100644
index 0000000..1535e8c
--- /dev/null
+++ b/src/tbf.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2013 by Holger Hans Peter Freyther
+ *
+ * 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+struct gprs_rlcmac_bts;
+
+int tbf_handle(struct gprs_rlcmac_bts *bts,
+		const uint32_t tlli, const char *imsi, const uint8_t ms_class,
+		const uint16_t delay_csec, const uint8_t *data, const uint16_t len);
-- 
1.8.4.rc3





More information about the osmocom-net-gprs mailing list