fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/30743 )
Change subject: trxcon: add initial GPRS L1 implementation - libl1gprs.la ......................................................................
trxcon: add initial GPRS L1 implementation - libl1gprs.la
Change-Id: I9567d64f9d00262e36147e8d7e541e5e246bda5f Related: OS#5500 --- M src/host/trxcon/configure.ac M src/host/trxcon/include/osmocom/bb/Makefile.am A src/host/trxcon/include/osmocom/bb/l1gprs/Makefile.am A src/host/trxcon/include/osmocom/bb/l1gprs/l1gprs.h A src/host/trxcon/include/osmocom/bb/l1gprs/logging.h M src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h M src/host/trxcon/include/osmocom/bb/trxcon/logging.h M src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h M src/host/trxcon/src/Makefile.am A src/host/trxcon/src/gprs.c M src/host/trxcon/src/logging.c M src/host/trxcon/src/trxcon_fsm.c M src/host/trxcon/src/trxcon_inst.c 13 files changed, 294 insertions(+), 3 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/43/30743/1
diff --git a/src/host/trxcon/configure.ac b/src/host/trxcon/configure.ac index 6508689..b22d1c8 100644 --- a/src/host/trxcon/configure.ac +++ b/src/host/trxcon/configure.ac @@ -16,6 +16,7 @@ PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore) PKG_CHECK_MODULES(LIBOSMOCODING, libosmocoding) PKG_CHECK_MODULES(LIBOSMOGSM, libosmogsm) +PKG_CHECK_MODULES(LIBOSMOGPRSRLCMAC, libosmo-gprs-rlcmac)
dnl checks for header files AC_HEADER_STDC @@ -63,6 +64,7 @@ include/osmocom/Makefile include/osmocom/bb/Makefile include/osmocom/bb/l1sched/Makefile + include/osmocom/bb/l1gprs/Makefile include/osmocom/bb/trxcon/Makefile src/Makefile Makefile]) diff --git a/src/host/trxcon/include/osmocom/bb/Makefile.am b/src/host/trxcon/include/osmocom/bb/Makefile.am index c26db00..183f6a5 100644 --- a/src/host/trxcon/include/osmocom/bb/Makefile.am +++ b/src/host/trxcon/include/osmocom/bb/Makefile.am @@ -1,4 +1,5 @@ SUBDIRS = \ l1sched \ + l1gprs \ trxcon \ $(NULL) diff --git a/src/host/trxcon/include/osmocom/bb/l1gprs/Makefile.am b/src/host/trxcon/include/osmocom/bb/l1gprs/Makefile.am new file mode 100644 index 0000000..e14a44e --- /dev/null +++ b/src/host/trxcon/include/osmocom/bb/l1gprs/Makefile.am @@ -0,0 +1,4 @@ +noinst_HEADERS = \ + l1gprs.h \ + logging.h \ + $(NULL) diff --git a/src/host/trxcon/include/osmocom/bb/l1gprs/l1gprs.h b/src/host/trxcon/include/osmocom/bb/l1gprs/l1gprs.h new file mode 100644 index 0000000..07e17d4 --- /dev/null +++ b/src/host/trxcon/include/osmocom/bb/l1gprs/l1gprs.h @@ -0,0 +1,40 @@ +#pragma once + +#include <stdbool.h> +#include <stdint.h> + +struct l1gprs_prim_data_ind { + uint32_t frame_nr; + size_t data_len; + const uint8_t *data; +}; + +struct l1gprs_grr_inst; + +struct l1gprs_pdch { + bool enabled; + uint8_t tn; /*!< Timeslot number */ + + /*! Backpointer to l1gprs_state we belong to */ + struct l1gprs_grr_inst *grr; +}; + +struct l1gprs_grr_inst { + /*! PDCH state for each timeslot */ + struct l1gprs_pdch pdch[8]; + /*! Logging context (used as prefix for messages) */ + const char *log_prefix; + /*! Some private data for API user */ + void *priv; +}; + +struct l1gprs_grr_inst *l1gprs_grr_inst_alloc(void *ctx, const char *log_prefix, void *priv); +void l1gprs_grr_inst_free(struct l1gprs_grr_inst *grr); + +int l1gprs_pdch_enable(struct l1gprs_pdch *pdch); +int l1gprs_pdch_disable(struct l1gprs_pdch *pdch); + +int l1gprs_handle_pdtch_ind(struct l1gprs_pdch *pdch, + const struct l1gprs_prim_data_ind *ind); +int l1gprs_handle_ptcch_ind(struct l1gprs_pdch *pdch, + const struct l1gprs_prim_data_ind *ind); diff --git a/src/host/trxcon/include/osmocom/bb/l1gprs/logging.h b/src/host/trxcon/include/osmocom/bb/l1gprs/logging.h new file mode 100644 index 0000000..422cc03 --- /dev/null +++ b/src/host/trxcon/include/osmocom/bb/l1gprs/logging.h @@ -0,0 +1,13 @@ +#pragma once + +extern int l1gprs_log_cat_grr; + +void l1gprs_logging_init(int logc); + +#define LOGP_GRR(grr, level, fmt, args...) \ + LOGP(l1gprs_log_cat_grr, level, "%s" fmt, \ + (grr)->log_prefix, ## args) + +#define LOGP_PDCH(pdch, level, fmt, args...) \ + LOGP_GRR((pdch->grr), level, "(PDCH-%u) " fmt, \ + (pdch->tn), ## args) diff --git a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h index 4b743ca..1efa00b 100644 --- a/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h +++ b/src/host/trxcon/include/osmocom/bb/l1sched/l1sched.h @@ -350,6 +350,8 @@ struct llist_head tx_prims; /*! Backpointer to the scheduler */ struct l1sched_state *sched; + /*! Some private data for API user */ + void *priv; };
/* Represents one TX primitive in the queue of l1sched_ts */ diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/logging.h b/src/host/trxcon/include/osmocom/bb/trxcon/logging.h index f8521a0..925f602 100644 --- a/src/host/trxcon/include/osmocom/bb/trxcon/logging.h +++ b/src/host/trxcon/include/osmocom/bb/trxcon/logging.h @@ -10,6 +10,7 @@ DTRXD, DSCH, DSCHD, + DGRR, };
int trxcon_logging_init(void *tall_ctx, const char *category_mask); diff --git a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h index 9148771..5af6cf9 100644 --- a/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h +++ b/src/host/trxcon/include/osmocom/bb/trxcon/trxcon.h @@ -4,6 +4,7 @@
struct osmo_fsm_inst; struct l1sched_state; +struct l1gprs_grr_inst; struct msgb;
struct trxcon_inst { @@ -18,6 +19,9 @@
/* The L1 scheduler */ struct l1sched_state *sched; + /* GPRS RR state (RLC/MAC layer) */ + struct l1gprs_grr_inst *grr; + /* PHY interface (e.g. TRXC/TRXD) */ void *phyif; /* L2 interface (e.g. L1CTL) */ @@ -40,6 +44,7 @@ TRXCON_LOGC_L1D, /* L1CTL data */ TRXCON_LOGC_SCHC, /* l1sched control */ TRXCON_LOGC_SCHD, /* l1sched data */ + TRXCON_LOGC_GRR, /* l1gprs logging */ };
void trxcon_set_log_cfg(const int *logc, unsigned int logc_num); diff --git a/src/host/trxcon/src/Makefile.am b/src/host/trxcon/src/Makefile.am index a286f2a..44546d1 100644 --- a/src/host/trxcon/src/Makefile.am +++ b/src/host/trxcon/src/Makefile.am @@ -8,6 +8,7 @@ $(LIBOSMOCORE_CFLAGS) \ $(LIBOSMOCODING_CFLAGS) \ $(LIBOSMOGSM_CFLAGS) \ + $(LIBOSMOGPRSRLCMAC_CFLAGS) \ $(NULL)
@@ -29,6 +30,19 @@ $(NULL)
+noinst_LTLIBRARIES += libl1gprs.la + +libl1gprs_la_SOURCES = \ + gprs.c \ + $(NULL) + +libl1gprs_la_LIBADD = \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOGPRSRLCMAC_LIBS) \ + $(NULL) + + noinst_LTLIBRARIES += libtrxcon.la
libtrxcon_la_SOURCES = \ @@ -51,6 +65,7 @@ trxcon_LDADD = \ libtrxcon.la \ libl1sched.la \ + libl1gprs.la \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOCODING_LIBS) \ $(LIBOSMOGSM_LIBS) \ diff --git a/src/host/trxcon/src/gprs.c b/src/host/trxcon/src/gprs.c new file mode 100644 index 0000000..a550946 --- /dev/null +++ b/src/host/trxcon/src/gprs.c @@ -0,0 +1,177 @@ +/* + * OsmocomBB <-> SDR connection bridge + * + * (C) 2022 by sysmocom - s.f.m.c. GmbH info@sysmocom.de + * Author: Vadim Yanitskiy vyanitskiy@sysmocom.de + * + * All Rights Reserved + * + * 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. + * + */ + +#include <errno.h> +#include <stdint.h> + +#include <osmocom/core/logging.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/bitvec.h> +#include <osmocom/core/utils.h> + +#include <osmocom/gsm/protocol/gsm_04_08.h> +#include <osmocom/gprs/rlcmac/gprs_rlcmac.h> +#include <osmocom/gprs/gprs_rlc.h> + +#include <osmocom/bb/l1gprs/l1gprs.h> +#include <osmocom/bb/l1gprs/logging.h> + +int l1gprs_log_cat_grr = DLGLOBAL; + +/* TODO: move to libosmo-gprs-rlcmac */ +enum gprs_rlcmac_block_type { + GPRS_RLCMAC_DATA_BLOCK = 0x00, + GPRS_RLCMAC_CONTROL_BLOCK = 0x01, + GPRS_RLCMAC_CONTROL_BLOCK_OPT = 0x02, + GPRS_RLCMAC_RESERVED = 0x03, +}; + +void l1gprs_logging_init(int logc) +{ + l1gprs_log_cat_grr = logc; +} + +struct l1gprs_grr_inst *l1gprs_grr_inst_alloc(void *ctx, const char *log_prefix, void *priv) +{ + struct l1gprs_grr_inst *grr; + + grr = talloc_zero(ctx, struct l1gprs_grr_inst); + if (grr == NULL) + return NULL; + + for (unsigned int tn = 0; tn < ARRAY_SIZE(grr->pdch); tn++) { + struct l1gprs_pdch *pdch = &grr->pdch[tn]; + + pdch->tn = tn; + pdch->grr = grr; + } + + if (log_prefix == NULL) + grr->log_prefix = talloc_asprintf(grr, "l1gprs[0x%p]: ", grr); + else + grr->log_prefix = talloc_strdup(grr, log_prefix); + grr->priv = priv; + + return grr; +} + +void l1gprs_grr_inst_free(struct l1gprs_grr_inst *grr) +{ + if (grr == NULL) + return; + + for (unsigned int tn = 0; tn < ARRAY_SIZE(grr->pdch); tn++) + l1gprs_pdch_disable(&grr->pdch[tn]); + talloc_free(grr); +} + +int l1gprs_pdch_enable(struct l1gprs_pdch *pdch) +{ + if (pdch->enabled) + return -EALREADY; + + pdch->enabled = true; + return 0; +} + +int l1gprs_pdch_disable(struct l1gprs_pdch *pdch) +{ + if (!pdch->enabled) + return -EALREADY; + + pdch->enabled = false; + return 0; +} + +static void handle_pdtch_gprs_block(struct l1gprs_pdch *pdch, + const enum osmo_gprs_cs cs, + const uint8_t *data, size_t data_len) +{ + const uint8_t pt = data[0] >> 6; + RlcMacDownlink_t *ctrl_block; + struct bitvec *bv; + + ctrl_block = talloc_zero(pdch->grr, RlcMacDownlink_t); + OSMO_ASSERT(ctrl_block != NULL); + + bv = bitvec_alloc(data_len, pdch->grr); + OSMO_ASSERT(bv != NULL); + bitvec_unpack(bv, data); + + switch (pt) { + case GPRS_RLCMAC_CONTROL_BLOCK: + osmo_gprs_rlcmac_decode_downlink(bv, ctrl_block); + break; + case GPRS_RLCMAC_DATA_BLOCK: /* TODO */ + default: + break; + } + + talloc_free(ctrl_block); + talloc_free(bv); +} + +int l1gprs_handle_pdtch_ind(struct l1gprs_pdch *pdch, + const struct l1gprs_prim_data_ind *ind) +{ + const enum osmo_gprs_cs cs = osmo_gprs_dl_cs_by_block_bytes(ind->data_len); + + if (!pdch->enabled) { + LOGP_PDCH(pdch, LOGL_ERROR, "Rx PDTCH/D block for disabled PDCH\n"); + return -ENODEV; + } + + switch (cs) { + case OSMO_GPRS_CS1: + case OSMO_GPRS_CS2: + case OSMO_GPRS_CS3: + case OSMO_GPRS_CS4: + handle_pdtch_gprs_block(pdch, cs, &ind->data[0], ind->data_len); + return 0; + case OSMO_GPRS_CS_NONE: + LOGP_PDCH(pdch, LOGL_ERROR, + "Failed to determine Coding Scheme (len=%zu)\n", ind->data_len); + return -EINVAL; + default: + LOGP_PDCH(pdch, LOGL_NOTICE, "Coding Scheme %d is not supported\n", cs); + return -ENOTSUP; + } +} + +int l1gprs_handle_ptcch_ind(struct l1gprs_pdch *pdch, + const struct l1gprs_prim_data_ind *ind) +{ + if (!pdch->enabled) { + LOGP_PDCH(pdch, LOGL_ERROR, "Rx PTCCH/D block for disabled PDCH\n"); + return -ENODEV; + } + + if (ind->data_len != GSM_MACBLOCK_LEN) { + LOGP_PDCH(pdch, LOGL_ERROR, + "Rx PTCCH/D block with unexpected length=%zu (expected %u)\n", + ind->data_len, GSM_MACBLOCK_LEN); + return -EINVAL; + } + + LOGP_PDCH(pdch, LOGL_INFO, "Rx PTCCH/D block: %s\n", + osmo_hexdump(ind->data, ind->data_len)); + + return 0; +} diff --git a/src/host/trxcon/src/logging.c b/src/host/trxcon/src/logging.c index 2222577..763a78d 100644 --- a/src/host/trxcon/src/logging.c +++ b/src/host/trxcon/src/logging.c @@ -67,6 +67,12 @@ .color = "\033[1;36m", .enabled = 1, .loglevel = LOGL_NOTICE, }, + [DGRR] = { + .name = "DGRR", + .description = "GPRS RR", + .color = "\033[1;36m", + .enabled = 1, .loglevel = LOGL_DEBUG, + }, };
static const struct log_info trxcon_log_info = { @@ -80,6 +86,7 @@ [TRXCON_LOGC_L1D] = DL1D, [TRXCON_LOGC_SCHC] = DSCH, [TRXCON_LOGC_SCHD] = DSCHD, + [TRXCON_LOGC_GRR] = DGRR, };
int trxcon_logging_init(void *tall_ctx, const char *category_mask) diff --git a/src/host/trxcon/src/trxcon_fsm.c b/src/host/trxcon/src/trxcon_fsm.c index 10663b1..575d75c 100644 --- a/src/host/trxcon/src/trxcon_fsm.c +++ b/src/host/trxcon/src/trxcon_fsm.c @@ -36,6 +36,7 @@ #include <osmocom/bb/trxcon/l1ctl.h> #include <osmocom/bb/l1sched/l1sched.h> #include <osmocom/bb/l1sched/logging.h> +#include <osmocom/bb/l1gprs/l1gprs.h>
#define S(x) (1 << (x))
@@ -537,11 +538,18 @@ case TRXCON_EV_RX_DATA_IND: { const struct trxcon_param_rx_data_ind *ind = data; + const unsigned int tn = ind->chan_nr & 0x07;
- if (ind->link_id == 0x00) - LOGPFSML(fi, LOGL_NOTICE, "Rx PDTCH/D message\n"); + const struct l1gprs_prim_data_ind grr_ind = { + .frame_nr = ind->frame_nr, + .data_len = ind->data_len, + .data = ind->data, + }; + + if (ind->link_id == L1SCHED_CH_LID_PTCCH) + l1gprs_handle_ptcch_ind(&trxcon->grr->pdch[tn], &grr_ind); else - LOGPFSML(fi, LOGL_NOTICE, "Rx PTCCH/D message\n"); + l1gprs_handle_pdtch_ind(&trxcon->grr->pdch[tn], &grr_ind); break; } case TRXCON_EV_DCH_EST_REQ: @@ -567,6 +575,10 @@ /* Shutdown the scheduler */ if (trxcon->sched != NULL) l1sched_free(trxcon->sched); + /* Shutdown GPRS RR layer */ + if (trxcon->grr == NULL) + l1gprs_grr_inst_free(trxcon->grr); + /* Close active connections */ if (trxcon->l2if != NULL) trxcon_l1ctl_close(trxcon); diff --git a/src/host/trxcon/src/trxcon_inst.c b/src/host/trxcon/src/trxcon_inst.c index 7d3813e..6db3a1b 100644 --- a/src/host/trxcon/src/trxcon_inst.c +++ b/src/host/trxcon/src/trxcon_inst.c @@ -27,6 +27,8 @@ #include <osmocom/bb/trxcon/trxcon_fsm.h> #include <osmocom/bb/l1sched/l1sched.h> #include <osmocom/bb/l1sched/logging.h> +#include <osmocom/bb/l1gprs/l1gprs.h> +#include <osmocom/bb/l1gprs/logging.h>
extern int g_logc_l1c; extern int g_logc_l1d; @@ -53,6 +55,9 @@ case TRXCON_LOGC_SCHD: schd = logc[i]; break; + case TRXCON_LOGC_GRR: + l1gprs_logging_init(logc[i]); + break; } }
@@ -91,6 +96,13 @@ return NULL; }
+ /* Init GPRS RR layer */ + trxcon->grr = l1gprs_grr_inst_alloc(trxcon, trxcon->log_prefix, trxcon); + if (trxcon->grr == NULL) { + trxcon_inst_free(trxcon); + return NULL; + } + return trxcon; }