pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmocom-bb/+/31007 )
Change subject: modem: Initial integration of libosmo-gprs-{llc,sndcp} ...................................................................... modem: Initial integration of libosmo-gprs-{llc,sndcp} Change-Id: I820328009ccdd1f8112aeb163efa064ec1465d2a --- M src/host/layer23/include/osmocom/bb/common/logging.h M src/host/layer23/include/osmocom/bb/common/settings.h M src/host/layer23/include/osmocom/bb/modem/Makefile.am A src/host/layer23/include/osmocom/bb/modem/llc.h A src/host/layer23/include/osmocom/bb/modem/sndcp.h M src/host/layer23/src/common/logging.c M src/host/layer23/src/modem/Makefile.am M src/host/layer23/src/modem/app_modem.c A src/host/layer23/src/modem/llc.c A src/host/layer23/src/modem/sndcp.c 10 files changed, 436 insertions(+), 2 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmocom-bb refs/changes/07/31007/1 diff --git a/src/host/layer23/include/osmocom/bb/common/logging.h b/src/host/layer23/include/osmocom/bb/common/logging.h index 5259f35..912b7d4 100644 --- a/src/host/layer23/include/osmocom/bb/common/logging.h +++ b/src/host/layer23/include/osmocom/bb/common/logging.h @@ -27,6 +27,8 @@ DLUA, DGAPK, DTUN, + DLLC, + DSNDCP, }; extern const struct log_info log_info; diff --git a/src/host/layer23/include/osmocom/bb/common/settings.h b/src/host/layer23/include/osmocom/bb/common/settings.h index 523ad8e..5e04894 100644 --- a/src/host/layer23/include/osmocom/bb/common/settings.h +++ b/src/host/layer23/include/osmocom/bb/common/settings.h @@ -183,6 +183,22 @@ struct gprs_settings { struct llist_head apn_list; + + /* RFC1144 TCP/IP header compression */ + struct { + int active; + int passive; + int s01; + } pcomp_rfc1144; + + /* V.42vis data compression */ + struct { + int active; + int passive; + int p0; + int p1; + int p2; + } dcomp_v42bis; }; int gprs_settings_init(struct osmocom_ms *ms); diff --git a/src/host/layer23/include/osmocom/bb/modem/Makefile.am b/src/host/layer23/include/osmocom/bb/modem/Makefile.am index 309a514..4a91c39 100644 --- a/src/host/layer23/include/osmocom/bb/modem/Makefile.am +++ b/src/host/layer23/include/osmocom/bb/modem/Makefile.am @@ -1,4 +1,6 @@ noinst_HEADERS = \ modem.h \ + llc.h \ + sndcp.h \ vty.h \ $(NULL) diff --git a/src/host/layer23/include/osmocom/bb/modem/llc.h b/src/host/layer23/include/osmocom/bb/modem/llc.h new file mode 100644 index 0000000..5fe5d49 --- /dev/null +++ b/src/host/layer23/include/osmocom/bb/modem/llc.h @@ -0,0 +1,8 @@ +#pragma once + +#include <stdbool.h> + +struct osmocom_ms; + +int modem_llc_init(struct osmocom_ms *ms, const char *cipher_plugin_path); + diff --git a/src/host/layer23/include/osmocom/bb/modem/sndcp.h b/src/host/layer23/include/osmocom/bb/modem/sndcp.h new file mode 100644 index 0000000..b2e6f0f --- /dev/null +++ b/src/host/layer23/include/osmocom/bb/modem/sndcp.h @@ -0,0 +1,10 @@ +#pragma once + +#include <stdbool.h> + +struct osmocom_ms; +struct osmobb_apn; + +int modem_sndcp_init(struct osmocom_ms *ms); +int modem_sndcp_sn_xid_req(struct osmobb_apn *apn); +int modem_sndcp_sn_unitdata_req(struct osmobb_apn *apn, uint8_t *npdu, size_t npdu_len); diff --git a/src/host/layer23/src/common/logging.c b/src/host/layer23/src/common/logging.c index 34c171f..66dc416 100644 --- a/src/host/layer23/src/common/logging.c +++ b/src/host/layer23/src/common/logging.c @@ -153,6 +153,18 @@ .color = "\033[0;37m", .enabled = 1, .loglevel = LOGL_NOTICE, }, + [DLLC] = { + .name = "DLLC", + .description = "GPRS Logical Link Control Protocol (LLC)", + .color = "\033[0;38m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, + [DSNDCP] = { + .name = "DSNDCP", + .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)", + .color = "\033[0;39m", + .enabled = 1, .loglevel = LOGL_NOTICE, + }, }; const struct log_info log_info = { diff --git a/src/host/layer23/src/modem/Makefile.am b/src/host/layer23/src/modem/Makefile.am index 4f369ad..e13ea2d 100644 --- a/src/host/layer23/src/modem/Makefile.am +++ b/src/host/layer23/src/modem/Makefile.am @@ -18,6 +18,8 @@ modem_SOURCES = \ $(top_srcdir)/src/common/main.c \ app_modem.c \ + llc.c \ + sndcp.c \ vty.c \ $(NULL) modem_LDADD = \ diff --git a/src/host/layer23/src/modem/app_modem.c b/src/host/layer23/src/modem/app_modem.c index 7f563a1..780ad61 100644 --- a/src/host/layer23/src/modem/app_modem.c +++ b/src/host/layer23/src/modem/app_modem.c @@ -47,6 +47,8 @@ #include <osmocom/bb/common/sysinfo.h> #include <osmocom/bb/common/apn.h> #include <osmocom/bb/common/tun.h> +#include <osmocom/bb/modem/llc.h> +#include <osmocom/bb/modem/sndcp.h> #include <osmocom/bb/modem/vty.h> #include <l1ctl_proto.h> @@ -101,8 +103,8 @@ LOGPAPN(LOGL_DEBUG, apn, "system wants to transmit IPv%c pkt to %s (%u bytes)\n", iph->version == 4 ? '4' : '6', osmo_sockaddr_ntop(&dst, addrstr), len); - /* TODO: prepare & transmit SNDCP UNITDATA.req */ - return 0; + rc = modem_sndcp_sn_unitdata_req(apn, pack, len); + return rc; } /* Generate a 8-bit CHANNEL REQUEST message as per 3GPP TS 44.018, 9.1.8 */ @@ -532,6 +534,8 @@ int l23_app_init(void) { + int rc; + l23_app_start = _modem_start; log_set_category_filter(osmo_stderr_target, DLGLOBAL, 1, LOGL_DEBUG); @@ -541,6 +545,16 @@ app_data.ms = osmocom_ms_alloc(l23_ctx, "1"); OSMO_ASSERT(app_data.ms); + if ((rc = modem_llc_init(app_data.ms, NULL))) { + LOGP(DLGLOBAL, LOGL_FATAL, "Failed initializing LLC layer\n"); + return rc; + } + + if ((rc = modem_sndcp_init(app_data.ms))) { + LOGP(DLGLOBAL, LOGL_FATAL, "Failed initializing SNDCP layer\n"); + return rc; + } + osmo_signal_register_handler(SS_L1CTL, &signal_cb, NULL); lapdm_channel_set_l3(&app_data.ms->lapdm_channel, &modem_rslms_cb, app_data.ms); return 0; diff --git a/src/host/layer23/src/modem/llc.c b/src/host/layer23/src/modem/llc.c new file mode 100644 index 0000000..adf945b --- /dev/null +++ b/src/host/layer23/src/modem/llc.c @@ -0,0 +1,172 @@ +/* GPRS LLC protocol implementation as per 3GPP TS 04.64 */ +/* (C) 2023 by sysmocom - s.m.f.c. GmbH <i...@sysmocom.de> + * All Rights Reserved + * Author: Pau Espin Pedrol <pes...@sysmocom.de> + * + * 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 <http://www.gnu.org/lienses/>. + * + */ + +#include <errno.h> +#include <stdint.h> +#include <stdbool.h> +#include <inttypes.h> + +#include <osmocom/core/msgb.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/rate_ctr.h> +#include <osmocom/crypt/kdf.h> +#include <osmocom/gprs/gprs_bssgp.h> +#include <osmocom/gsm/gsm_utils.h> +#include <osmocom/gprs/llc/llc_prim.h> +#include <osmocom/gprs/llc/llc.h> +#include <osmocom/gprs/sndcp/sndcp_prim.h> + +#include <osmocom/bb/common/logging.h> +#include <osmocom/bb/common/apn.h> +#include <osmocom/bb/common/ms.h> +#include <osmocom/bb/common/tun.h> +#include <osmocom/bb/modem/llc.h> + +LLIST_HEAD(sgsn_llmes); + +static int sgsn_llc_handle_ll_gmm(struct osmo_gprs_llc_prim *llc_prim) +{ + struct msgb *msg; + + switch (llc_prim->oph.primitive) { + case OSMO_GPRS_LLC_LL_UNITDATA: + break; + case OSMO_GPRS_LLC_LL_RESET: + case OSMO_GPRS_LLC_LL_ESTABLISH: + case OSMO_GPRS_LLC_LL_XID: + case OSMO_GPRS_LLC_LL_DATA: + case OSMO_GPRS_LLC_LL_STATUS: + default: + LOGP(DLLC, LOGL_NOTICE, "%s(): Unexpected Rx LL prim %u\n", + __func__, llc_prim->oph.primitive); + return -EINVAL; + } + + msg = msgb_alloc(4096, "gsm0408_rx"); + msgb_tlli(msg) = llc_prim->ll.tlli; + msgb_gmmh(msg) = msgb_put(msg, llc_prim->ll.l3_pdu_len); + if (llc_prim->ll.l3_pdu_len > 0) { + memcpy(msgb_gmmh(msg), llc_prim->ll.l3_pdu, llc_prim->ll.l3_pdu_len); + } + //TODO: submit to GMM? + //TODO: free msg? + return 0; +} + +static int sgsn_llc_handle_ll_sndcp(struct osmo_gprs_llc_prim *llc_prim) +{ + int rc; + switch (llc_prim->oph.primitive) { + case OSMO_GPRS_LLC_LL_RESET: + case OSMO_GPRS_LLC_LL_ESTABLISH: + case OSMO_GPRS_LLC_LL_XID: + case OSMO_GPRS_LLC_LL_DATA: + case OSMO_GPRS_LLC_LL_UNITDATA: + case OSMO_GPRS_LLC_LL_STATUS: + /* Forward it to upper layers, pass owneserip over to SNDCP: */ + osmo_gprs_sndcp_prim_lower_up(llc_prim); + rc = 1; /* Tell LLC that we take ownership of the prim. */ + break; + default: + LOGP(DLLC, LOGL_NOTICE, "%s(): Unexpected Rx LL prim %u\n", + __func__, llc_prim->oph.primitive); + rc = -EINVAL; + } + return rc; +} + +int sgsn_llc_prim_up_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; + + switch (llc_prim->oph.sap) { + case OSMO_GPRS_LLC_SAP_LLGM: + LOGP(DLLC, LOGL_DEBUG, "%s(): Rx %s TLLI=0x%08x\n", + __func__, pdu_name, llc_prim->llgmm.tlli); + break; + case OSMO_GPRS_LLC_SAP_LL: + LOGP(DLLC, LOGL_DEBUG, "%s(): Rx %s TLLI=0x%08x SAPI=%s l3=[%s]\n", + __func__, pdu_name, llc_prim->ll.tlli, + osmo_gprs_llc_sapi_name(llc_prim->ll.sapi), + osmo_hexdump(llc_prim->ll.l3_pdu, llc_prim->ll.l3_pdu_len)); + + switch (llc_prim->ll.sapi) { + case OSMO_GPRS_LLC_SAPI_GMM: + rc = sgsn_llc_handle_ll_gmm(llc_prim); + break; + case OSMO_GPRS_LLC_SAPI_SNDCP3: + case OSMO_GPRS_LLC_SAPI_SNDCP5: + case OSMO_GPRS_LLC_SAPI_SNDCP9: + case OSMO_GPRS_LLC_SAPI_SNDCP11: + rc = sgsn_llc_handle_ll_sndcp(llc_prim); + break; + case OSMO_GPRS_LLC_SAPI_TOM2: + case OSMO_GPRS_LLC_SAPI_SMS: + case OSMO_GPRS_LLC_SAPI_TOM8: + LOGP(DLLC, LOGL_NOTICE, "%s(): Unimplemented Rx llc_sapi %s\n", __func__, pdu_name); + rc = -EINVAL; + break; + default: + LOGP(DLLC, LOGL_NOTICE, "%s(): Unexpected Rx llc_sapi %s\n", __func__, pdu_name); + rc = -EINVAL; + break; + } + break; + default: + LOGP(DLLC, LOGL_NOTICE, "%s(): Unexpected Rx %s\n", __func__, pdu_name); + OSMO_ASSERT(0); + } + return rc; +} + +int sgsn_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; + + switch (llc_prim->oph.sap) { + case OSMO_GPRS_LLC_SAP_GRR: + LOGP(DLLC, LOGL_DEBUG, "%s(): Rx %s l3=[%s]\n", __func__, pdu_name, + osmo_hexdump(llc_prim->grr.ll_pdu, llc_prim->grr.ll_pdu_len)); + OSMO_ASSERT(0); + break; + default: + LOGP(DLLC, LOGL_DEBUG, "%s(): Unexpected Rx %s\n", __func__, pdu_name); + OSMO_ASSERT(0); + } + return rc; +} + +int modem_llc_init(struct osmocom_ms *ms, const char *cipher_plugin_path) +{ + int rc; + rc = osmo_gprs_llc_init(OSMO_GPRS_LLC_LOCATION_MS, cipher_plugin_path); + if (rc != 0) + return rc; + + osmo_gprs_llc_set_log_cat(OSMO_GPRS_LLC_LOGC_LLC, DLLC); + + osmo_gprs_llc_prim_set_up_cb(sgsn_llc_prim_up_cb, ms); + osmo_gprs_llc_prim_set_down_cb(sgsn_llc_prim_down_cb, ms); + return rc; +} diff --git a/src/host/layer23/src/modem/sndcp.c b/src/host/layer23/src/modem/sndcp.c new file mode 100644 index 0000000..673aad8 --- /dev/null +++ b/src/host/layer23/src/modem/sndcp.c @@ -0,0 +1,196 @@ +/* GPRS SNDCP User/SN/SNSM interfaces as per 3GPP TS 04.65 */ +/* (C) 2023 by sysmocom - s.m.f.c. GmbH <i...@sysmocom.de> + * All Rights Reserved + * Author: Pau Espin Pedrol <pes...@sysmocom.de> + * + * 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 <http://www.gnu.org/lienses/>. + * + */ + +#include <stdbool.h> +#include <stdint.h> +#include <errno.h> +#include <stdio.h> + +#include <netinet/ip.h> +#include <netinet/ip6.h> + +#include <osmocom/core/msgb.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/timer.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/endian.h> + +#include <osmocom/gprs/llc/llc.h> +#include <osmocom/gprs/llc/llc_prim.h> +#include <osmocom/gprs/sndcp/sndcp_prim.h> +#include <osmocom/gprs/sndcp/sndcp.h> + +#include <osmocom/bb/common/logging.h> +#include <osmocom/bb/common/apn.h> +#include <osmocom/bb/common/ms.h> +#include <osmocom/bb/common/tun.h> +#include <osmocom/bb/modem/sndcp.h> + +/* Received SN-XID.cnf from SNDCP layer: */ +static int modem_sndcp_handle_sn_xid_cnf(struct osmobb_apn *apn, struct osmo_gprs_sndcp_prim *sndcp_prim) +{ + LOGP(DSNDCP, LOGL_ERROR, "%s(): Rx SN-XID.cnf: TODO IMPLEMENT!\n", __func__); + return 0; +} + +/* Received SN-UNITDTA.ind from SNDCP layer: */ +static int modem_sndcp_handle_sn_unitdata_ind(struct osmobb_apn *apn, struct osmo_gprs_sndcp_prim *sndcp_prim) +{ + const char *npdu_name = osmo_gprs_sndcp_prim_name(sndcp_prim); + int rc; + + LOGP(DSNDCP, LOGL_DEBUG, "Rx %s TLLI=0x%08x SAPI=%s NSAPI=%u NPDU=[%s]\n", + npdu_name, + sndcp_prim->sn.tlli, osmo_gprs_llc_sapi_name(sndcp_prim->sn.sapi), + sndcp_prim->sn.data_req.nsapi, + osmo_hexdump(sndcp_prim->sn.data_ind.npdu, sndcp_prim->sn.data_ind.npdu_len)); + + rc = tun_encaps(apn->tun.tun, sndcp_prim->sn.data_ind.npdu, sndcp_prim->sn.data_ind.npdu_len); + return rc; +} + +static int modem_sndcp_prim_up_cb(struct osmo_gprs_sndcp_prim *sndcp_prim, void *user_data) +{ + struct osmocom_ms *ms = user_data; + struct osmobb_apn *apn; + const char *npdu_name = osmo_gprs_sndcp_prim_name(sndcp_prim); + int rc = 0; + + if (sndcp_prim->oph.sap != OSMO_GPRS_SNDCP_SAP_SN) { + LOGP(DSNDCP, LOGL_ERROR, "%s(): Unexpected Rx %s\n", __func__, npdu_name); + OSMO_ASSERT(0); + } + + /* TODO: properly retrieve APN/PDP based on TLLI/SAPI/NSAPI: */ + apn = llist_first_entry_or_null(&ms->gprs.apn_list, struct osmobb_apn, list); + if (!apn) { + LOGP(DSNDCP, LOGL_NOTICE, "Unable to find destination APN: Rx %s\n", npdu_name); + return -ENODEV; + } + + switch (OSMO_PRIM_HDR(&sndcp_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_SNDCP_SN_UNITDATA, PRIM_OP_INDICATION): + rc = modem_sndcp_handle_sn_unitdata_ind(apn, sndcp_prim); + break; + case OSMO_PRIM(OSMO_GPRS_SNDCP_SN_XID, PRIM_OP_CONFIRM): + rc = modem_sndcp_handle_sn_xid_cnf(apn, sndcp_prim); + break; + default: + LOGP(DSNDCP, LOGL_ERROR, "%s(): Rx %s UNIMPLEMENTED\n", __func__, npdu_name); + break; + }; + return rc; +} + +static int modem_sndcp_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; + + if (llc_prim->oph.sap != OSMO_GPRS_LLC_SAP_LL) { + LOGP(DSNDCP, LOGL_ERROR, "%s(): Unexpected Rx %s\n", __func__, pdu_name); + OSMO_ASSERT(0); + } + + switch (OSMO_PRIM_HDR(&llc_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_LLC_LL_UNITDATA, PRIM_OP_REQUEST): + LOGP(DSNDCP, LOGL_DEBUG, "%s(): Rx %s TLLI=0x%08x SAPI=%s L3=[%s]\n", + __func__, pdu_name, + llc_prim->ll.tlli, osmo_gprs_llc_sapi_name(llc_prim->ll.sapi), + osmo_hexdump(llc_prim->ll.l3_pdu, llc_prim->ll.l3_pdu_len)); + rc = osmo_gprs_llc_prim_upper_down(llc_prim); + rc = 1; /* Tell SNDCP layer we took msgb ownsership and transfer it to LLC */ + break; + default: + LOGP(DSNDCP, LOGL_ERROR, "%s(): Rx %s UNIMPLEMENTED\n", __func__, pdu_name); + break; + }; + return rc; +} + +static int modem_sndcp_prim_snsm_cb(struct osmo_gprs_sndcp_prim *sndcp_prim, void *user_data) +{ + const char *npdu_name = osmo_gprs_sndcp_prim_name(sndcp_prim); + + if (sndcp_prim->oph.sap != OSMO_GPRS_SNDCP_SAP_SNSM) { + LOGP(DSNDCP, LOGL_ERROR, "%s(): Unexpected Rx %s\n", __func__, npdu_name); + OSMO_ASSERT(0); + } + + LOGP(DSNDCP, LOGL_ERROR, "%s(): Rx %s UNIMPLEMENTED\n", __func__, npdu_name); + return 0; +} + + +int modem_sndcp_init(struct osmocom_ms *ms) +{ + int rc; + rc = osmo_gprs_sndcp_init(); + if (rc != 0) + return rc; + + osmo_gprs_sndcp_set_log_cat(OSMO_GPRS_SNDCP_LOGC_SNDCP, DSNDCP); + osmo_gprs_sndcp_set_log_cat(OSMO_GPRS_SNDCP_LOGC_SLHC, DSNDCP); + + osmo_gprs_sndcp_prim_set_up_cb(modem_sndcp_prim_up_cb, ms); + osmo_gprs_sndcp_prim_set_down_cb(modem_sndcp_prim_down_cb, ms); + osmo_gprs_sndcp_prim_set_snsm_cb(modem_sndcp_prim_snsm_cb, ms); + return rc; +} + +int modem_sndcp_sn_xid_req(struct osmobb_apn *apn) +{ + struct osmo_gprs_sndcp_prim *sndcp_prim; + int rc; + struct osmocom_ms *ms = apn->ms; + struct gprs_settings *set = &ms->gprs; + + /* TODO: look up PDP context IDs from ms once we have GMM layer. */ + uint32_t tlli = 0xe1c5d364; + uint8_t sapi = OSMO_GPRS_LLC_SAPI_SNDCP3; + uint8_t nsapi = 1; + + sndcp_prim = osmo_gprs_sndcp_prim_alloc_sn_xid_req(tlli, sapi, nsapi); + OSMO_ASSERT(sndcp_prim); + sndcp_prim->sn.xid_req.pcomp_rfc1144.active = set->pcomp_rfc1144.active; + sndcp_prim->sn.xid_req.pcomp_rfc1144.s01 = set->pcomp_rfc1144.s01; + sndcp_prim->sn.xid_req.dcomp_v42bis.active = set->dcomp_v42bis.active; + sndcp_prim->sn.xid_req.dcomp_v42bis.p0 = set->dcomp_v42bis.p0; + sndcp_prim->sn.xid_req.dcomp_v42bis.p1 = set->dcomp_v42bis.p1; + sndcp_prim->sn.xid_req.dcomp_v42bis.p2 = set->dcomp_v42bis.p2; + rc = osmo_gprs_sndcp_prim_upper_down(sndcp_prim); + return rc; +} + +int modem_sndcp_sn_unitdata_req(struct osmobb_apn *apn, uint8_t *npdu, size_t npdu_len) +{ + struct osmo_gprs_sndcp_prim *sndcp_prim; + int rc; + + /* TODO: look up PDP context IDs from apn->ms once we have GMM layer. */ + uint32_t tlli = 0xe1c5d364; + uint8_t sapi = OSMO_GPRS_LLC_SAPI_SNDCP3; + uint8_t nsapi = 1; + + sndcp_prim = osmo_gprs_sndcp_prim_alloc_sn_unitdata_req(tlli, sapi, nsapi, npdu, npdu_len); + OSMO_ASSERT(sndcp_prim); + rc = osmo_gprs_sndcp_prim_upper_down(sndcp_prim); + return rc; +} \ No newline at end of file -- To view, visit https://gerrit.osmocom.org/c/osmocom-bb/+/31007 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmocom-bb Gerrit-Branch: master Gerrit-Change-Id: I820328009ccdd1f8112aeb163efa064ec1465d2a Gerrit-Change-Number: 31007 Gerrit-PatchSet: 1 Gerrit-Owner: pespin <pes...@sysmocom.de> Gerrit-MessageType: newchange