From 60716bcfe6dac4a77ff367a59b314b1bd4e56ad0 Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Wed, 25 Jan 2023 20:41:54 +0100 Subject: [PATCH] modem: Initial integration of libosmo-gprs-rlcmac This commit places code to forward unitdata LLC<->RLCMAC. Depends: libosmo-gprs.git Change-Id I1870fa6a264612c5a669bfb832e6e8c0a892cb74 Related: OS#5500 Change-Id: I0e628d9ddaa5ad6a205f07746d4176d1b8df7eb0 --- .../include/osmocom/bb/common/logging.h | 1 + .../include/osmocom/bb/modem/Makefile.am | 1 + .../layer23/include/osmocom/bb/modem/rlcmac.h | 8 + src/host/layer23/src/common/logging.c | 10 +- src/host/layer23/src/modem/Makefile.am | 1 + src/host/layer23/src/modem/app_modem.c | 6 + src/host/layer23/src/modem/llc.c | 15 +- src/host/layer23/src/modem/rlcmac.c | 138 ++++++++++++++++++ 8 files changed, 177 insertions(+), 3 deletions(-) create mode 100644 src/host/layer23/include/osmocom/bb/modem/rlcmac.h create mode 100644 src/host/layer23/src/modem/rlcmac.c diff --git a/src/host/layer23/include/osmocom/bb/common/logging.h b/src/host/layer23/include/osmocom/bb/common/logging.h index 912b7d451..818b14952 100644 --- a/src/host/layer23/include/osmocom/bb/common/logging.h +++ b/src/host/layer23/include/osmocom/bb/common/logging.h @@ -27,6 +27,7 @@ enum { DLUA, DGAPK, DTUN, + DRLCMAC, DLLC, DSNDCP, }; diff --git a/src/host/layer23/include/osmocom/bb/modem/Makefile.am b/src/host/layer23/include/osmocom/bb/modem/Makefile.am index 4a91c3954..4acb21b01 100644 --- a/src/host/layer23/include/osmocom/bb/modem/Makefile.am +++ b/src/host/layer23/include/osmocom/bb/modem/Makefile.am @@ -1,6 +1,7 @@ noinst_HEADERS = \ modem.h \ llc.h \ + rlcmac.h \ sndcp.h \ vty.h \ $(NULL) diff --git a/src/host/layer23/include/osmocom/bb/modem/rlcmac.h b/src/host/layer23/include/osmocom/bb/modem/rlcmac.h new file mode 100644 index 000000000..d1b054f8e --- /dev/null +++ b/src/host/layer23/include/osmocom/bb/modem/rlcmac.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +struct osmocom_ms; + +int modem_rlcmac_init(struct osmocom_ms *ms); + diff --git a/src/host/layer23/src/common/logging.c b/src/host/layer23/src/common/logging.c index 66dc4161d..a31eb2293 100644 --- a/src/host/layer23/src/common/logging.c +++ b/src/host/layer23/src/common/logging.c @@ -153,16 +153,22 @@ static const struct log_info_cat default_categories[] = { .color = "\033[0;37m", .enabled = 1, .loglevel = LOGL_NOTICE, }, + [DRLCMAC] = { + .name = "DRLCMAC", + .description = "Radio Link Control / Medium Access Control (RLC/MAC)", + .color = "\033[0;38m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, [DLLC] = { .name = "DLLC", .description = "GPRS Logical Link Control Protocol (LLC)", - .color = "\033[0;38m", + .color = "\033[0;39m", .enabled = 1, .loglevel = LOGL_NOTICE, }, [DSNDCP] = { .name = "DSNDCP", .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)", - .color = "\033[0;39m", + .color = "\033[0;40m", .enabled = 1, .loglevel = LOGL_NOTICE, }, }; diff --git a/src/host/layer23/src/modem/Makefile.am b/src/host/layer23/src/modem/Makefile.am index e13ea2d06..7ce71dc95 100644 --- a/src/host/layer23/src/modem/Makefile.am +++ b/src/host/layer23/src/modem/Makefile.am @@ -19,6 +19,7 @@ modem_SOURCES = \ $(top_srcdir)/src/common/main.c \ app_modem.c \ llc.c \ + rlcmac.c \ sndcp.c \ vty.c \ $(NULL) diff --git a/src/host/layer23/src/modem/app_modem.c b/src/host/layer23/src/modem/app_modem.c index 1be2cbcfd..14fdf2f1d 100644 --- a/src/host/layer23/src/modem/app_modem.c +++ b/src/host/layer23/src/modem/app_modem.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -552,6 +553,11 @@ int l23_app_init(void) app_data.ms = osmocom_ms_alloc(l23_ctx, "1"); OSMO_ASSERT(app_data.ms); + if ((rc = modem_rlcmac_init(app_data.ms))) { + LOGP(DRLCMAC, LOGL_FATAL, "Failed initializing RLC/MAC layer\n"); + return rc; + } + if ((rc = modem_llc_init(app_data.ms, NULL))) { LOGP(DLLC, LOGL_FATAL, "Failed initializing LLC layer\n"); return rc; diff --git a/src/host/layer23/src/modem/llc.c b/src/host/layer23/src/modem/llc.c index 196c2409c..4bb0684b2 100644 --- a/src/host/layer23/src/modem/llc.c +++ b/src/host/layer23/src/modem/llc.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -141,10 +142,22 @@ int modem_llc_prim_down_cb(struct osmo_gprs_llc_prim *llc_prim, void *user_data) const char *pdu_name = osmo_gprs_llc_prim_name(llc_prim); int rc = 0; + osmo_static_assert(sizeof(struct osmo_gprs_llc_grr_prim) == sizeof(struct osmo_gprs_rlcmac_grr_prim), + _grr_prim_size); + switch (llc_prim->oph.sap) { case OSMO_GPRS_LLC_SAP_GRR: - LOGP(DLLC, LOGL_DEBUG, "%s(): Rx %s l3=[%s]\n", __func__, pdu_name, + LOGP(DLLC, LOGL_DEBUG, "%s(): Rx %s ll=[%s]\n", __func__, pdu_name, osmo_hexdump(llc_prim->grr.ll_pdu, llc_prim->grr.ll_pdu_len)); + /* Forward it to lower layers, pass ownership over to RLCMAC: */ + /* Optimization: LLC-GRR-UNITDATA-IND is 1-to-1 ABI compatible with + RLCMAC-GRR-UNITDATA-IND, we just need to adapt the header. + See osmo_static_assert(_grr_prim_size) above. + */ + llc_prim->oph.sap = OSMO_GPRS_RLCMAC_SAP_GRR; + llc_prim->oph.primitive = OSMO_GPRS_RLCMAC_GRR_UNITDATA; + osmo_gprs_rlcmac_prim_upper_down((struct osmo_gprs_rlcmac_prim *)llc_prim); + rc = 1; /* Tell RLCMAC that we take ownership of the prim. */ break; default: LOGP(DLLC, LOGL_DEBUG, "%s(): Unexpected Rx %s\n", __func__, pdu_name); diff --git a/src/host/layer23/src/modem/rlcmac.c b/src/host/layer23/src/modem/rlcmac.c new file mode 100644 index 000000000..83dcd6cc4 --- /dev/null +++ b/src/host/layer23/src/modem/rlcmac.c @@ -0,0 +1,138 @@ +/* GPRS RLC/MAC protocol implementation as per 3GPP TS 44.060 */ +/* (C) 2023 by sysmocom - s.m.f.c. GmbH + * All Rights Reserved + * Author: Pau Espin Pedrol + * + * 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 . + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +static int modem_rlcmac_handle_grr(struct osmo_gprs_rlcmac_prim *rlcmac_prim) +{ + int rc; + + osmo_static_assert(sizeof(struct osmo_gprs_rlcmac_grr_prim) == sizeof(struct osmo_gprs_llc_grr_prim), + _grr_prim_size); + + switch (rlcmac_prim->oph.primitive) { + case OSMO_GPRS_RLCMAC_GRR_UNITDATA: + /* Forward it to upper layers, pass ownership over to LLC: */ + /* Optimization: RLCMAC-GRR-UNITDATA-IND is 1-to-1 ABI compatible with + LLC-GRR-UNITDATA-IND, we just need to adapt the header. + See osmo_static_assert(_grr_prim_size) above. + */ + rlcmac_prim->oph.sap = OSMO_GPRS_LLC_SAP_GRR; + rlcmac_prim->oph.primitive = OSMO_GPRS_LLC_GRR_UNITDATA; + osmo_gprs_llc_prim_lower_up((struct osmo_gprs_llc_prim *)rlcmac_prim); + rc = 1; /* Tell RLCMAC that we take ownership of the prim. */ + break; + case OSMO_GPRS_RLCMAC_GRR_DATA: + default: + LOGP(DRLCMAC, LOGL_NOTICE, "%s(): Unexpected Rx RLCMAC GRR prim %u\n", + __func__, rlcmac_prim->oph.primitive); + rc = -EINVAL; + break; + } + return rc; +} + +static int modem_rlcmac_handle_gmmrr(struct osmo_gprs_rlcmac_prim *rlcmac_prim) +{ + int rc; + switch (rlcmac_prim->oph.primitive) { + case OSMO_GPRS_RLCMAC_GMMRR_PAGE: + LOGP(DRLCMAC, LOGL_ERROR, "%s(): TODO: implement answering to paging indication TLLI=0x%08x\n", + __func__, rlcmac_prim->gmmrr.page_ind.tlli); + rc = 0; + break; + default: + LOGP(DRLCMAC, LOGL_NOTICE, "%s(): Unexpected Rx RLCMAC GMMRR prim %u\n", + __func__, rlcmac_prim->oph.primitive); + rc = -EINVAL; + } + return rc; +} + +static int modem_rlcmac_prim_up_cb(struct osmo_gprs_rlcmac_prim *rlcmac_prim, void *user_data) +{ + const char *pdu_name = osmo_gprs_rlcmac_prim_name(rlcmac_prim); + int rc = 0; + + switch (rlcmac_prim->oph.sap) { + case OSMO_GPRS_RLCMAC_SAP_GRR: + LOGP(DRLCMAC, LOGL_DEBUG, "%s(): Rx %s TLLI=0x%08x ll=[%s]\n", + __func__, pdu_name, rlcmac_prim->grr.tlli, + osmo_hexdump(rlcmac_prim->grr.ll_pdu, rlcmac_prim->grr.ll_pdu_len)); + rc = modem_rlcmac_handle_grr(rlcmac_prim); + break; + case OSMO_GPRS_RLCMAC_SAP_GMMRR: + LOGP(DRLCMAC, LOGL_DEBUG, "%s(): Rx %s\n", + __func__, pdu_name); + rc = modem_rlcmac_handle_gmmrr(rlcmac_prim); + break; + default: + LOGP(DRLCMAC, LOGL_NOTICE, "%s(): Unexpected Rx %s\n", __func__, pdu_name); + OSMO_ASSERT(0); + } + return rc; +} + +static int modem_rlcmac_prim_down_cb(struct osmo_gprs_rlcmac_prim *rlcmac_prim, void *user_data) +{ + const char *pdu_name = osmo_gprs_rlcmac_prim_name(rlcmac_prim); + int rc = 0; + + switch (rlcmac_prim->oph.sap) { + default: + LOGP(DRLCMAC, LOGL_DEBUG, "%s(): Unexpected Rx %s\n", __func__, pdu_name); + OSMO_ASSERT(0); + } + return rc; +} + +int modem_rlcmac_init(struct osmocom_ms *ms) +{ + int rc; + rc = osmo_gprs_rlcmac_init(OSMO_GPRS_RLCMAC_LOCATION_MS); + if (rc != 0) + return rc; + + osmo_gprs_rlcmac_set_log_cat(OSMO_GPRS_RLCMAC_LOGC_RLCMAC, DRLCMAC); + + osmo_gprs_rlcmac_prim_set_up_cb(modem_rlcmac_prim_up_cb, ms); + osmo_gprs_rlcmac_prim_set_down_cb(modem_rlcmac_prim_down_cb, ms); + return rc; +}