pespin has submitted this change. ( https://gerrit.osmocom.org/c/osmocom-bb/+/32155 )
Change subject: modem: initial SM layer support through libosmo-gprs-sm ......................................................................
modem: initial SM layer support through libosmo-gprs-sm
Depends: libosmo-gprs.git Change-Id I9b4a9a6364f7799540475e7e1d10ab2310768281 Related: OS#5501 Change-Id: I9476d93954c7dc348e6f97ca89eaa651f802f9a0 --- M src/host/layer23/configure.ac M src/host/layer23/include/osmocom/bb/common/logging.h M src/host/layer23/include/osmocom/bb/modem/Makefile.am A src/host/layer23/include/osmocom/bb/modem/sm.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/sm.c M src/host/layer23/src/modem/vty.c 9 files changed, 228 insertions(+), 0 deletions(-)
Approvals: fixeria: Looks good to me, approved pespin: Verified
diff --git a/src/host/layer23/configure.ac b/src/host/layer23/configure.ac index 1434fbf..b4eb860 100644 --- a/src/host/layer23/configure.ac +++ b/src/host/layer23/configure.ac @@ -50,6 +50,7 @@ PKG_CHECK_MODULES(LIBOSMOGPRSLLC, libosmo-gprs-llc) PKG_CHECK_MODULES(LIBOSMOGPRSSNDCP, libosmo-gprs-sndcp) PKG_CHECK_MODULES(LIBOSMOGPRSGMM, libosmo-gprs-gmm) +PKG_CHECK_MODULES(LIBOSMOGPRSSM, libosmo-gprs-sm) AC_CHECK_LIB(gps, gps_waiting, LIBGPS_CFLAGS=" -D_HAVE_GPSD" LIBGPS_LIBS=" -lgps ",,) AC_SUBST([LIBGPS_CFLAGS]) AC_SUBST([LIBGPS_LIBS]) diff --git a/src/host/layer23/include/osmocom/bb/common/logging.h b/src/host/layer23/include/osmocom/bb/common/logging.h index fc0861e..fa76c59 100644 --- a/src/host/layer23/include/osmocom/bb/common/logging.h +++ b/src/host/layer23/include/osmocom/bb/common/logging.h @@ -31,6 +31,7 @@ DLLC, DSNDCP, DGMM, + DSM };
extern const struct log_info log_info; diff --git a/src/host/layer23/include/osmocom/bb/modem/Makefile.am b/src/host/layer23/include/osmocom/bb/modem/Makefile.am index 6dfc98e..2f69d19 100644 --- a/src/host/layer23/include/osmocom/bb/modem/Makefile.am +++ b/src/host/layer23/include/osmocom/bb/modem/Makefile.am @@ -4,6 +4,7 @@ grr.h \ llc.h \ rlcmac.h \ + sm.h \ sndcp.h \ vty.h \ $(NULL) diff --git a/src/host/layer23/include/osmocom/bb/modem/sm.h b/src/host/layer23/include/osmocom/bb/modem/sm.h new file mode 100644 index 0000000..51000cf --- /dev/null +++ b/src/host/layer23/include/osmocom/bb/modem/sm.h @@ -0,0 +1,7 @@ +#pragma once + +#include <stdbool.h> + +struct osmocom_ms; + +int modem_sm_init(struct osmocom_ms *ms); diff --git a/src/host/layer23/src/common/logging.c b/src/host/layer23/src/common/logging.c index e3a5beb..d1b5b92 100644 --- a/src/host/layer23/src/common/logging.c +++ b/src/host/layer23/src/common/logging.c @@ -177,6 +177,12 @@ .color = "\033[0;32m", .enabled = 1, .loglevel = LOGL_NOTICE, }, + [DSM] = { + .name = "DSM", + .description = "GPRS Session Management (SM)", + .color = "\033[0;31m", + .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 086c2f3..935722b 100644 --- a/src/host/layer23/src/modem/Makefile.am +++ b/src/host/layer23/src/modem/Makefile.am @@ -12,6 +12,7 @@ $(LIBOSMOGPRSLLC_CFLAGS) \ $(LIBOSMOGPRSSNDCP_CFLAGS) \ $(LIBOSMOGPRSGMM_CFLAGS) \ + $(LIBOSMOGPRSSM_CFLAGS) \ $(NULL)
bin_PROGRAMS = modem @@ -23,6 +24,7 @@ grr.c \ llc.c \ rlcmac.c \ + sm.c \ sndcp.c \ vty.c \ $(NULL) @@ -35,4 +37,5 @@ $(LIBOSMOGPRSLLC_LIBS) \ $(LIBOSMOGPRSSNDCP_LIBS) \ $(LIBOSMOGPRSGMM_LIBS) \ + $(LIBOSMOGPRSSM_LIBS) \ $(NULL) diff --git a/src/host/layer23/src/modem/app_modem.c b/src/host/layer23/src/modem/app_modem.c index cecf4e6..644c630 100644 --- a/src/host/layer23/src/modem/app_modem.c +++ b/src/host/layer23/src/modem/app_modem.c @@ -51,6 +51,7 @@ #include <osmocom/bb/modem/llc.h> #include <osmocom/bb/modem/sndcp.h> #include <osmocom/bb/modem/gmm.h> +#include <osmocom/bb/modem/sm.h> #include <osmocom/bb/modem/vty.h> #include <osmocom/bb/modem/grr.h>
@@ -180,6 +181,11 @@ return rc; }
+ if ((rc = modem_sm_init(app_data.ms))) { + LOGP(DSM, LOGL_FATAL, "Failed initializing SM layer\n"); + return rc; + } + osmo_signal_register_handler(SS_L1CTL, &signal_cb, NULL); lapdm_channel_set_l3(&app_data.ms->lapdm_channel, &modem_grr_rslms_cb, app_data.ms); return 0; diff --git a/src/host/layer23/src/modem/sm.c b/src/host/layer23/src/modem/sm.c new file mode 100644 index 0000000..5dc80e0 --- /dev/null +++ b/src/host/layer23/src/modem/sm.c @@ -0,0 +1,120 @@ +/* GPRS SM interfaces as per 3GPP TS 24.008, TS 24.007 */ +/* (C) 2023 by sysmocom - s.m.f.c. GmbH info@sysmocom.de + * All Rights Reserved + * Author: Pau Espin Pedrol pespin@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 <string.h> +#include <stdint.h> +#include <errno.h> +#include <stdio.h> + +#include <osmocom/core/msgb.h> +#include <osmocom/core/prim.h> +#include <osmocom/core/utils.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/tun.h> +#include <osmocom/gsm/protocol/gsm_04_08_gprs.h> + +#include <osmocom/gprs/gmm/gmm.h> +#include <osmocom/gprs/gmm/gmm_prim.h> +#include <osmocom/gprs/sm/sm_prim.h> +#include <osmocom/gprs/sm/sm.h> +#include <osmocom/gprs/rlcmac/rlcmac_prim.h> + +#include <osmocom/bb/common/settings.h> +#include <osmocom/bb/common/logging.h> +#include <osmocom/bb/common/apn.h> +#include <osmocom/bb/common/ms.h> +#include <osmocom/bb/modem/sm.h> + +static int modem_sm_prim_up_cb(struct osmo_gprs_sm_prim *sm_prim, void *user_data) +{ + const char *pdu_name = osmo_gprs_sm_prim_name(sm_prim); + int rc = 0; + + switch (sm_prim->oph.sap) { + case OSMO_GPRS_SM_SAP_SMREG: + switch (OSMO_PRIM_HDR(&sm_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_ACTIVATE, PRIM_OP_CONFIRM): + if (sm_prim->smreg.pdp_act_cnf.accepted) + LOGP(DSM, LOGL_INFO, "%s(): Rx %s (TODO: set IP address in tun device)\n", __func__, pdu_name); + else + LOGP(DSM, LOGL_INFO, "%s(): Rx %s: Activate PDP failed! cause '%s'\n", __func__, pdu_name, + get_value_string(gsm48_gsm_cause_names, sm_prim->smreg.pdp_act_cnf.rej.cause)); + break; + case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_ACTIVATE, PRIM_OP_INDICATION): + case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_DEACTIVATE, PRIM_OP_CONFIRM): + case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_DEACTIVATE, PRIM_OP_INDICATION): + case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_MODIFY, PRIM_OP_CONFIRM): + case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_MODIFY, PRIM_OP_INDICATION): + case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_ACTIVATE_SEC, PRIM_OP_CONFIRM): + default: + LOGP(DSM, LOGL_ERROR, "%s(): Rx %s UNIMPLEMENTED\n", __func__, pdu_name); + break; + }; + break; + default: + LOGP(DSM, LOGL_ERROR, "%s(): Unexpected Rx %s\n", __func__, pdu_name); + OSMO_ASSERT(0); + } + + return rc; +} + +static int modem_sm_prim_down_cb(struct osmo_gprs_sm_prim *sm_prim, void *user_data) +{ + const char *pdu_name = osmo_gprs_sm_prim_name(sm_prim); + int rc = 0; + + switch (sm_prim->oph.sap) { + default: + LOGP(DSM, LOGL_ERROR, "%s(): Unexpected Rx %s\n", __func__, pdu_name); + OSMO_ASSERT(0); + } + + return rc; +} + +static int modem_sm_prim_gmm_down_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data) +{ + int rc; + + rc = osmo_gprs_gmm_prim_upper_down(gmm_prim); + + /* GMM took ownership of the message, tell SM layer to not free it: */ + rc = 1; + return rc; +} + +int modem_sm_init(struct osmocom_ms *ms) +{ + int rc; + rc = osmo_gprs_sm_init(OSMO_GPRS_SM_LOCATION_MS); + if (rc != 0) + return rc; + + osmo_gprs_sm_set_log_cat(OSMO_GPRS_SM_LOGC_SM, DSM); + + osmo_gprs_sm_prim_set_up_cb(modem_sm_prim_up_cb, ms); + osmo_gprs_sm_prim_set_down_cb(modem_sm_prim_down_cb, ms); + osmo_gprs_sm_prim_set_gmm_down_cb(modem_sm_prim_gmm_down_cb, ms); + + return rc; +} diff --git a/src/host/layer23/src/modem/vty.c b/src/host/layer23/src/modem/vty.c index 68a46b8..a23ae73 100644 --- a/src/host/layer23/src/modem/vty.c +++ b/src/host/layer23/src/modem/vty.c @@ -26,6 +26,8 @@ #include <osmocom/gprs/llc/llc.h> #include <osmocom/gprs/llc/llc_prim.h> #include <osmocom/gprs/gmm/gmm_prim.h> +#include <osmocom/gprs/sm/sm_prim.h> +
#include <osmocom/vty/vty.h> #include <osmocom/vty/command.h> @@ -62,6 +64,7 @@ #define GRR_CMDG_DESC "GPRS RR specific commands\n" #define LLC_CMDG_DESC "GPRS LLC specific commands\n" #define GMM_CMDG_DESC "GPRS GMM specific commands\n" +#define SM_CMDG_DESC "GPRS SM specific commands\n"
/* testing commands */ DEFUN_HIDDEN(test_grr_tx_chan_req, @@ -212,6 +215,74 @@ return CMD_SUCCESS; }
+DEFUN_HIDDEN(test_sm_act_pdp_ctx, + test_sm_act_pdp_ctx_cmd, + "test MS_NAME sm act-pdp-ctx APN", + TEST_CMD_DESC MS_NAME_DESC SM_CMDG_DESC + "Enqueue a SM SMREG-ACTIVATE.req for transmission\n" + "APN to activate\n") +{ + struct osmo_gprs_sm_prim *sm_prim; + struct osmocom_ms *ms; + struct osmobb_apn *apn; + + uint8_t nsapi = 6; + enum osmo_gprs_sm_llc_sapi llc_sapi = OSMO_GPRS_SM_LLC_SAPI_SAPI3; + struct osmo_sockaddr pdp_addr_any = {0}; + uint8_t qos[OSMO_GPRS_SM_QOS_MAXLEN] = {0}; + uint8_t pco[OSMO_GPRS_SM_QOS_MAXLEN] = {0}; + uint32_t ptmsi = 0x00000000; + char *imsi = "1234567890"; + char *imei = "42342342342342"; + char *imeisv = "4234234234234275"; + enum osmo_gprs_sm_pdp_addr_ietf_type pdp_addr_ietf_type; + + if ((ms = l23_vty_get_ms(argv[0], vty)) == NULL) { + vty_out(vty, "Unable to find MS '%s'%s", argv[0], VTY_NEWLINE); + return CMD_WARNING; + } + + apn = ms_find_apn_by_name(ms, argv[1]); + if (!apn) { + vty_out(vty, "Unable to find APN '%s'%s", argv[1], VTY_NEWLINE); + return CMD_WARNING; + } + + if (apn->cfg.apn_type_mask & APN_TYPE_IPv4v6) { + pdp_addr_ietf_type = OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4V6; + } else if (apn->cfg.apn_type_mask & APN_TYPE_IPv4) { + pdp_addr_ietf_type = OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4; + } else if (apn->cfg.apn_type_mask & APN_TYPE_IPv6) { + pdp_addr_ietf_type = OSMO_GPRS_SM_PDP_ADDR_IETF_IPV6; + } else { + vty_out(vty, "APN '%s' has no PDP address type set%s", argv[1], VTY_NEWLINE); + return CMD_WARNING; + } + + sm_prim = osmo_gprs_sm_prim_alloc_smreg_pdp_act_req(); + sm_prim->smreg.pdp_act_req.nsapi = nsapi; + sm_prim->smreg.pdp_act_req.llc_sapi = llc_sapi; + sm_prim->smreg.pdp_act_req.pdp_addr_ietf_type = pdp_addr_ietf_type; + sm_prim->smreg.pdp_act_req.pdp_addr_v4 = pdp_addr_any; + sm_prim->smreg.pdp_act_req.pdp_addr_v6 = pdp_addr_any; + memcpy(sm_prim->smreg.pdp_act_req.qos, qos, sizeof(qos)); + sm_prim->smreg.pdp_act_req.qos_len = 1; + memcpy(sm_prim->smreg.pdp_act_req.pco, pco, sizeof(pco)); + sm_prim->smreg.pdp_act_req.pco_len = 1; + OSMO_STRLCPY_ARRAY(sm_prim->smreg.pdp_act_req.apn, apn->cfg.name); + sm_prim->smreg.pdp_act_req.gmm.ptmsi = ptmsi; + OSMO_STRLCPY_ARRAY(sm_prim->smreg.pdp_act_req.gmm.imsi, imsi); + OSMO_STRLCPY_ARRAY(sm_prim->smreg.pdp_act_req.gmm.imei, imei); + OSMO_STRLCPY_ARRAY(sm_prim->smreg.pdp_act_req.gmm.imeisv, imeisv); + + if (osmo_gprs_sm_prim_upper_down(sm_prim) != 0) { + vty_out(vty, "Failed to enqueue a SM PDU%s", VTY_NEWLINE); + return CMD_WARNING; + } + + return CMD_SUCCESS; +} + /* per APN config */ DEFUN(cfg_ms_apn, cfg_ms_apn_cmd, "apn APN_NAME", "Configure an APN\n" @@ -397,6 +468,7 @@ install_element_ve(&test_llc_unitdata_req_gmm_attch_cmd); install_element_ve(&test_gmm_reg_attach_cmd); install_element_ve(&test_gmm_reg_detach_cmd); + install_element_ve(&test_sm_act_pdp_ctx_cmd); install_element(CONFIG_NODE, &l23_cfg_ms_cmd);
install_element(MS_NODE, &cfg_ms_apn_cmd);