Create skeleton for libosmo-gprs-gmm

The library itself only contains a bunch of boilerplate to build the
library and have usual initialization, logging, prim APIs.
There's not yet much logic specific in it yet, but will make next
commits easier to review.

Related: OS#5501
Change-Id: Ie098576954a55e5046c2463390ab7133511c1eb3
This commit is contained in:
Pau Espin 2023-03-14 17:14:53 +01:00
parent f829a685ad
commit 146643b0f3
23 changed files with 836 additions and 0 deletions

View File

@ -15,6 +15,7 @@ SUBDIRS = \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = \
libosmo-csn1.pc \
libosmo-gprs-gmm.pc \
libosmo-gprs-llc.pc \
libosmo-gprs-rlcmac.pc \
libosmo-gprs-sndcp.pc \

View File

@ -75,6 +75,7 @@ AC_MSG_RESULT([CPPFLAGS="$CPPFLAGS"])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([libosmo-csn1.pc
libosmo-gprs-gmm.pc
libosmo-gprs-llc.pc
libosmo-gprs-rlcmac.pc
libosmo-gprs-sndcp.pc
@ -82,15 +83,18 @@ AC_CONFIG_FILES([libosmo-csn1.pc
include/osmocom/Makefile
include/osmocom/csn1/Makefile
include/osmocom/gprs/Makefile
include/osmocom/gprs/gmm/Makefile
include/osmocom/gprs/llc/Makefile
include/osmocom/gprs/rlcmac/Makefile
include/osmocom/gprs/sndcp/Makefile
src/Makefile
src/csn1/Makefile
src/gmm/Makefile
src/llc/Makefile
src/rlcmac/Makefile
src/sndcp/Makefile
tests/Makefile
tests/gmm/Makefile
tests/llc/Makefile
tests/rlcmac/Makefile
tests/sndcp/Makefile

View File

@ -41,6 +41,24 @@ Requires: libosmo-csn1-0 = %{version}
This package provides development files for compiling a program using
libosmo-csn1 - CSN.1 (Concrete Syntax Notation 1) codec.
%package -n libosmo-gprs-gmm0
Summary: Osmocom GPRS GMM library
License: AGPL-3.0-or-later
Group: System/Libraries
%description -n libosmo-gprs-gmm0
This package provides GMM (GPRS Mobility Management) layer for (E)GPRS.
%package -n libosmo-gprs-gmm-devel
Summary: Development files for libosmo-gprs-gmm
License: AGPL-3.0-or-later
Group: Development/Libraries/C and C++
Requires: libosmo-gprs-gmm0 = %{version}
%description -n libosmo-gprs-gmm-devel
This package provides development files for compiling a program using
libosmo-gprs-gmm - GMM (GPRS Mobility Management) layer for (E)GPRS.
%package -n libosmo-gprs-llc0
Summary: Osmocom GPRS LLC library
License: AGPL-3.0-or-later
@ -114,6 +132,8 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
%post -n libosmo-csn1-0 -p /sbin/ldconfig
%postun -n libosmo-csn1-0 -p /sbin/ldconfig
%post -n libosmo-gprs-gmm0 -p /sbin/ldconfig
%postun -n libosmo-gprs-gmm0 -p /sbin/ldconfig
%post -n libosmo-gprs-llc0 -p /sbin/ldconfig
%postun -n libosmo-gprs-llc0 -p /sbin/ldconfig
%post -n libosmo-gprs-rlcmac0 -p /sbin/ldconfig
@ -131,6 +151,17 @@ make %{?_smp_mflags} check || (find . -name testsuite.log -exec cat {} +)
%_libdir/libosmo-csn1.so
%_libdir/pkgconfig/libosmo-csn1.pc
%files -n libosmo-gprs-gmm0
%_libdir/libosmo-gprs-gmm.so.0*
%files -n libosmo-gprs-gmm-devel
%dir %_includedir/%name
%dir %_includedir/%name/osmocom
%dir %_includedir/%name/osmocom/gprs
%_includedir/%name/osmocom/gprs/gmm
%_libdir/libosmo-gprs-gmm.so
%_libdir/pkgconfig/libosmo-gprs-gmm.pc
%files -n libosmo-gprs-llc0
%_libdir/libosmo-gprs-llc.so.0*

25
debian/control vendored
View File

@ -43,6 +43,31 @@ Depends: libosmo-csn1-0 (= ${binary:Version}),
${misc:Depends}
Description: Development headers and libraries for the Osmocom CSN.1 codec
Package: libosmo-gprs-gmm0
Section: libs
Architecture: any
Multi-Arch: same
Pre-Depends: ${misc:Pre-Depends}
Depends: ${misc:Depends},
${shlibs:Depends}
Description: Osmocom GMM (GPRS Mobility Management) layer for GPRS and EGPRS
Package: libosmo-gprs-gmm-dbg
Architecture: any
Section: debug
Multi-Arch: same
Depends: libosmo-gprs-gmm0 (= ${binary:Version}),
${misc:Depends}
Description: Debug symbols for libosmo-gprs-gmm
Package: libosmo-gprs-gmm-dev
Architecture: any
Multi-Arch: same
Section: libdevel
Depends: libosmo-gprs-gmm0 (= ${binary:Version}),
${misc:Depends}
Description: Development headers and libraries for libosmo-gprs-gmm
Package: libosmo-gprs-llc0
Section: libs
Architecture: any

5
debian/libosmo-gprs-gmm-dev.install vendored Normal file
View File

@ -0,0 +1,5 @@
usr/include/osmocom/gprs/gmm
usr/lib/*/libosmo-gprs-gmm*.a
usr/lib/*/libosmo-gprs-gmm*.so
usr/lib/*/libosmo-gprs-gmm*.la
usr/lib/*/pkgconfig/libosmo-gprs-gmm.pc

1
debian/libosmo-gprs-gmm0.install vendored Normal file
View File

@ -0,0 +1 @@
usr/lib/*/libosmo-gprs-gmm*.so.*

View File

@ -1,4 +1,5 @@
SUBDIRS = \
gmm \
llc \
rlcmac \
sndcp \

View File

@ -0,0 +1,11 @@
noinst_HEADERS = \
gmm_private.h \
$(NULL)
gmm_HEADERS = \
gmm.h \
gmm_prim.h \
$(NULL)
gmmdir = $(includedir)/osmocom/gprs/gmm

View File

@ -0,0 +1,22 @@
#pragma once
/* GPRS Mobility Management (GMM) definitions from 3GPP TS 24.008 */
#include <stdint.h>
#include <stddef.h>
/* Use stack as MS or as network? */
enum osmo_gprs_gmm_location {
OSMO_GPRS_GMM_LOCATION_UNSET,
OSMO_GPRS_GMM_LOCATION_MS,
OSMO_GPRS_GMM_LOCATION_NETWORK,
};
int osmo_gprs_gmm_init(enum osmo_gprs_gmm_location location);
enum osmo_gprs_gmm_log_cat {
OSMO_GPRS_GMM_LOGC_GMM,
_OSMO_GPRS_GMM_LOGC_MAX,
};
void osmo_gprs_gmm_set_log_cat(enum osmo_gprs_gmm_log_cat logc, int logc_num);

View File

@ -0,0 +1,102 @@
#pragma once
/* 3GPP TS 44.065, section 5 "Service primitives and functions" */
/* 3GPP TS 24.007:
* section 6.6 "Registration Services for GPRS-Services"
* section 9.4 "Services provided by the LLC entity for GPRS services (GSM only)"
* section 9.5 "Services provided by the GMM for GPRS services"
*/
#include <stdint.h>
#include <stddef.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/prim.h>
#include <osmocom/gprs/gmm/gmm.h>
/* 3GPP TS 24.007 (index, "GMMR") */
enum osmo_gprs_gmm_prim_sap {
OSMO_GPRS_GMM_SAP_GMMREG, /* 6.6 */
OSMO_GPRS_GMM_SAP_GMMRR, /* GSM only */
OSMO_GPRS_GMM_SAP_GMMAS, /* UMTS only */
OSMO_GPRS_GMM_SAP_LLGMM,
OSMO_GPRS_GMM_SAP_GMMSM,
OSMO_GPRS_GMM_SAP_GMMSMS,
OSMO_GPRS_GMM_SAP_GMMRABM, /* UMTS only */
OSMO_GPRS_GMM_SAP_GMMSS,
OSMO_GPRS_GMM_SAP_GMMSS2,
};
extern const struct value_string osmo_gprs_gmm_prim_sap_names[];
static inline const char *osmo_gprs_gmm_prim_sap_name(enum osmo_gprs_gmm_prim_sap val)
{
return get_value_string(osmo_gprs_gmm_prim_sap_names, val);
}
/* 6.6 Registration Services for GPRS-Services */
enum osmo_gprs_gmm_gmmreg_prim_type {
OSMO_GPRS_GMM_GMMREG_ATTACH, /* Req/Cnf/Rej */
OSMO_GPRS_GMM_GMMREG_DETACH, /* Req/Cnf/Ind */
};
extern const struct value_string osmo_gprs_gmm_gmmreg_prim_type_names[];
static inline const char *osmo_gprs_gmm_gmmreg_prim_type_name(enum osmo_gprs_gmm_gmmreg_prim_type val)
{
return get_value_string(osmo_gprs_gmm_gmmreg_prim_type_names, val);
}
/* Parameters for OSMO_GPRS_GMM_GMMREG_* prims */
struct osmo_gprs_gmm_gmmreg_prim {
/* Common fields */
/* Specific fields */
union {
/* OSMO_GPRS_GMM_GMMREG_ATTACH | Req, 6.6.1.1 */
struct {
/* attach-type, READY-timer, STANDBY-timer */
} attach_req;
/* OSMO_GPRS_GMM_GMMREG_ATTACH | Cnf 6.6.1.2 / Rej 6.6.1.3 */
struct {
bool accepted;
union {
struct {
/* PLMNs MT-caps, attach-type. */
} acc;
struct {
uint8_t cause;
} rej;
};
} attach_cnf;
/* OSMO_GPRS_GMM_GMMREG_DETACH | Req, 6.6.1.4 */
struct {
/* detach-type, power-off/normal-detach */
} detach_req;
/* OSMO_GPRS_GMM_GMMREG_DETACH | Cnf, 6.6.1.5 */
struct {
/* detach-type */
} detach_cnf;
/* OSMO_GPRS_GMM_GMMREG_DETACH | Ind, , 6.6.1.6 */
struct {
/* detach-type */
} detach_ind;
};
};
struct osmo_gprs_gmm_prim {
struct osmo_prim_hdr oph;
union {
struct osmo_gprs_gmm_gmmreg_prim gmmreg;
};
};
typedef int (*osmo_gprs_gmm_prim_up_cb)(struct osmo_gprs_gmm_prim *gmm_prim, void *up_user_data);
void osmo_gprs_gmm_prim_set_up_cb(osmo_gprs_gmm_prim_up_cb up_cb, void *up_user_data);
typedef int (*osmo_gprs_gmm_prim_down_cb)(struct osmo_gprs_gmm_prim *gmm_prim, void *down_user_data);
void osmo_gprs_gmm_prim_set_down_cb(osmo_gprs_gmm_prim_down_cb down_cb, void *down_user_data);
int osmo_gprs_gmm_prim_upper_down(struct osmo_gprs_gmm_prim *gmm_prim);
int osmo_gprs_gmm_prim_lower_up(struct osmo_gprs_gmm_prim *gmm_prim);
const char *osmo_gprs_gmm_prim_name(const struct osmo_gprs_gmm_prim *gmm_prim);
/* Alloc primitive for GMMREG SAP: */
struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmreg_attach_req(void);

View File

@ -0,0 +1,52 @@
#pragma once
/* 3GPP TS 24.008, private header */
#include <stdint.h>
#include <stddef.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/endian.h>
#include <osmocom/gprs/gmm/gmm.h>
extern int g_gmm_log_cat[_OSMO_GPRS_GMM_LOGC_MAX];
#define LOGGMM(lvl, fmt, args...) LOGP(g_gmm_log_cat[OSMO_GPRS_GMM_LOGC_GMM], lvl, fmt, ## args)
#define msgb_gmm_prim(msg) ((struct osmo_gprs_gmm_prim *)(msg)->l1h)
struct gprs_gmm_ctx {
enum osmo_gprs_gmm_location location;
osmo_gprs_gmm_prim_up_cb gmm_up_cb;
void *gmm_up_cb_user_data;
osmo_gprs_gmm_prim_down_cb gmm_down_cb;
void *gmm_down_cb_user_data;
struct llist_head gmme_list; /* list of struct gprs_gmm_entity->list */
};
extern struct gprs_gmm_ctx *g_ctx;
/* GMM Entity: */
struct gprs_gmm_entity {
struct llist_head list; /* item in (struct gprs_gmm_ctx)->gmme_list */
};
/* gmm_prim.c: */
struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmm_gmmreg_attach_cnf(void);
int gprs_gmm_prim_call_up_cb(struct osmo_gprs_gmm_prim *gmm_prim);
int gprs_gmm_prim_call_down_cb(struct osmo_gprs_gmm_prim *gmm_prim);
/* gmm.c: */
struct gprs_gmm_entity *gprs_gmm_gmme_alloc(void);
void gprs_gmm_gmme_free(struct gprs_gmm_entity *gmme);
#define LOGGMME(snme, level, fmt, args...) \
LOGGMM(level, "GMME(%08x) " fmt, \
23 /*TODO: use ID */, \
## args)

12
libosmo-gprs-gmm.pc.in Normal file
View File

@ -0,0 +1,12 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: Osmocom [E]GPRS GMM (GPRS Mobility Management) Library
Description: C Utility Library
Version: @VERSION@
Requires: libosmocore
Libs: -L${libdir} -losmo-gprs-gmm
Libs.private: -ltalloc
Cflags: -I${includedir}/

View File

@ -3,4 +3,5 @@ SUBDIRS = \
llc \
rlcmac \
sndcp \
gmm \
$(NULL)

37
src/gmm/Makefile.am Normal file
View File

@ -0,0 +1,37 @@
# This is _NOT_ the library release version, it's an API version.
# Please read Chapter 6 "Library interface versions" of the libtool
# documentation before making any modification
LIBVERSION=0:0:0
AM_CPPFLAGS = \
$(all_includes) \
-I$(top_srcdir)/include \
$(NULL)
AM_CFLAGS = \
-Wall \
$(LIBOSMOGSM_CFLAGS) \
$(LIBOSMOCORE_CFLAGS) \
$(NULL)
lib_LTLIBRARIES = \
libosmo-gprs-gmm.la \
$(NULL)
libosmo_gprs_gmm_la_SOURCES = \
gmm.c \
gmm_prim.c \
misc.c \
$(NULL)
libosmo_gprs_gmm_la_LDFLAGS = \
-export-symbols-regex '^osmo_' \
-version-info $(LIBVERSION) \
-no-undefined \
$(NULL)
libosmo_gprs_gmm_la_LIBADD = \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \
-lm \
$(NULL)

66
src/gmm/gmm.c Normal file
View File

@ -0,0 +1,66 @@
/* GPRS GMM as per 3GPP TS 24.008, TS 24.007 */
/*
* (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
* 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/licenses/>.
*
*/
#include <stdint.h>
#include <errno.h>
#include <arpa/inet.h>
#include <osmocom/core/talloc.h>
#include <osmocom/gprs/gmm/gmm.h>
#include <osmocom/gprs/gmm/gmm_prim.h>
#include <osmocom/gprs/gmm/gmm_private.h>
struct gprs_gmm_ctx *g_ctx;
int osmo_gprs_gmm_init(enum osmo_gprs_gmm_location location)
{
if (g_ctx)
talloc_free(g_ctx);
g_ctx = talloc_zero(NULL, struct gprs_gmm_ctx);
g_ctx->location = location;
INIT_LLIST_HEAD(&g_ctx->gmme_list);
return 0;
}
struct gprs_gmm_entity *gprs_gmm_gmme_alloc(void)
{
struct gprs_gmm_entity *gmme;
gmme = talloc_zero(g_ctx, struct gprs_gmm_entity);
if (!gmme)
return NULL;
llist_add(&gmme->list, &g_ctx->gmme_list);
return gmme;
}
void gprs_gmm_gmme_free(struct gprs_gmm_entity *gmme)
{
if (!gmme)
return;
LOGGMME(gmme, LOGL_DEBUG, "free()\n");
llist_del(&gmme->list);
talloc_free(gmme);
}

292
src/gmm/gmm_prim.c Normal file
View File

@ -0,0 +1,292 @@
/* GMM service primitive implementation as per 3GPP TS 44.065 */
/*
* (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
* 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/licenses/>.
*
*/
#include <stdint.h>
#include <errno.h>
#include <osmocom/core/msgb.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/logging.h>
#include <osmocom/gprs/gmm/gmm.h>
#include <osmocom/gprs/gmm/gmm_prim.h>
#include <osmocom/gprs/gmm/gmm_private.h>
#define GMM_MSGB_HEADROOM 0
const struct value_string osmo_gprs_gmm_prim_sap_names[] = {
{ OSMO_GPRS_GMM_SAP_GMMREG, "GMMREG" },
{ OSMO_GPRS_GMM_SAP_GMMRR, "GMRR" },
{ OSMO_GPRS_GMM_SAP_GMMAS, "GMMAS" },
{ OSMO_GPRS_GMM_SAP_LLGMM, "LLGMM" },
{ OSMO_GPRS_GMM_SAP_GMMSM, "GMMSM" },
{ OSMO_GPRS_GMM_SAP_GMMSMS, "GMMSMS" },
{ OSMO_GPRS_GMM_SAP_GMMRABM, "GMMRABM" },
{ OSMO_GPRS_GMM_SAP_GMMSS, "GMMSS" },
{ OSMO_GPRS_GMM_SAP_GMMSS2, "GMMSS2" },
{ 0, NULL }
};
const struct value_string osmo_gprs_gmm_gmmreg_prim_type_names[] = {
{ OSMO_GPRS_GMM_GMMREG_ATTACH, "ATTACH" },
{ OSMO_GPRS_GMM_GMMREG_DETACH, "DETACH" },
{ 0, NULL }
};
const char *osmo_gprs_gmm_prim_name(const struct osmo_gprs_gmm_prim *gmm_prim)
{
static char name_buf[256];
const char *sap = osmo_gprs_gmm_prim_sap_name(gmm_prim->oph.sap);
const char *op = get_value_string(osmo_prim_op_names, gmm_prim->oph.operation);
const char *type;
switch (gmm_prim->oph.sap) {
case OSMO_GPRS_GMM_SAP_GMMREG:
type = osmo_gprs_gmm_gmmreg_prim_type_name(gmm_prim->oph.primitive);
break;
default:
type = "unsupported-gmm-sap";
}
snprintf(name_buf, sizeof(name_buf), "%s-%s.%s", sap, type, op);
return name_buf;
}
static int gmm_up_cb_dummy(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data)
{
LOGGMM(LOGL_INFO, "gmm_up_cb_dummy(%s)\n", osmo_gprs_gmm_prim_name(gmm_prim));
return 0;
}
static int gmm_down_cb_dummy(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data)
{
LOGGMM(LOGL_INFO, "gmm_down_cb_dummy(%s)\n", osmo_gprs_gmm_prim_name(gmm_prim));
return 0;
}
/* Set callback used by GMM layer to push primitives to higher layers in protocol stack */
void osmo_gprs_gmm_prim_set_up_cb(osmo_gprs_gmm_prim_up_cb up_cb, void *up_user_data)
{
g_ctx->gmm_up_cb = up_cb;
g_ctx->gmm_up_cb_user_data = up_user_data;
}
/* Set callback used by GMM layer to push primitives to lower layers in protocol stack */
void osmo_gprs_gmm_prim_set_down_cb(osmo_gprs_gmm_prim_down_cb down_cb, void *down_user_data)
{
g_ctx->gmm_down_cb = down_cb;
g_ctx->gmm_down_cb_user_data = down_user_data;
}
/********************************
* Primitive allocation:
********************************/
/* allocate a msgb containing a struct osmo_gprs_gmm_prim + optional l3 data */
static struct msgb *gprs_gmm_prim_msgb_alloc(unsigned int npdu_len)
{
const int headroom = GMM_MSGB_HEADROOM;
const int size = headroom + sizeof(struct osmo_gprs_gmm_prim) + npdu_len;
struct msgb *msg = msgb_alloc_headroom(size, headroom, "gmm_prim");
if (!msg)
return NULL;
msg->l1h = msgb_put(msg, sizeof(struct osmo_gprs_gmm_prim));
return msg;
}
struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc(unsigned int sap, unsigned int type,
enum osmo_prim_operation operation,
unsigned int extra_size)
{
struct msgb *msg = gprs_gmm_prim_msgb_alloc(extra_size);
struct osmo_gprs_gmm_prim *gmm_prim = msgb_gmm_prim(msg);
osmo_prim_init(&gmm_prim->oph, sap, type, operation, msg);
return gmm_prim;
}
/*** SN ***/
static inline struct osmo_gprs_gmm_prim *gmm_prim_gmmreg_alloc(enum osmo_gprs_gmm_gmmreg_prim_type type,
enum osmo_prim_operation operation,
unsigned int extra_size)
{
return gprs_gmm_prim_alloc(OSMO_GPRS_GMM_SAP_GMMREG, type, operation, extra_size);
}
/* TS 24.007 6.6.1.1 GMMREG-ATTACH.request */
struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmreg_attach_req(void)
{
struct osmo_gprs_gmm_prim *gmm_prim;
gmm_prim = gmm_prim_gmmreg_alloc(OSMO_GPRS_GMM_GMMREG_ATTACH, PRIM_OP_REQUEST, 0);
return gmm_prim;
}
/* 6.6.1.2 GMMREG-ATTACH.cnf */
struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmreg_attach_cnf(void)
{
struct osmo_gprs_gmm_prim *gmm_prim;
gmm_prim = gmm_prim_gmmreg_alloc(OSMO_GPRS_GMM_GMMREG_ATTACH, PRIM_OP_CONFIRM, 0);
gmm_prim->gmmreg.attach_cnf.accepted = true;
/* TODO: gmm_prim->gmmreg.attach_cnf.acc.* */
return gmm_prim;
}
/* TODO: 6.6.1.3 GMMREG-ATTACH.rej */
/* TS 24.007 6.6.1.4 GMMREG-DETACH.request */
struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_detach_req(void)
{
struct osmo_gprs_gmm_prim *gmm_prim;
gmm_prim = gmm_prim_gmmreg_alloc(OSMO_GPRS_GMM_GMMREG_DETACH, PRIM_OP_REQUEST, 0);
return gmm_prim;
}
/* TS 24.007 6.6.1.5 GMMREG-DETACH.cnf */
struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmreg_detach_cnf(void)
{
struct osmo_gprs_gmm_prim *gmm_prim;
gmm_prim = gmm_prim_gmmreg_alloc(OSMO_GPRS_GMM_GMMREG_DETACH, PRIM_OP_CONFIRM, 0);
return gmm_prim;
}
/* TS 24.007 6.6.1.6 GMMREG-DETACH.cnf */
struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmreg_detach_ind(void)
{
struct osmo_gprs_gmm_prim *gmm_prim;
gmm_prim = gmm_prim_gmmreg_alloc(OSMO_GPRS_GMM_GMMREG_DETACH, PRIM_OP_INDICATION, 0);
return gmm_prim;
}
static int gprs_gmm_prim_handle_unsupported(struct osmo_gprs_gmm_prim *gmm_prim)
{
LOGGMM(LOGL_ERROR, "Unsupported gmm_prim! %s\n", osmo_gprs_gmm_prim_name(gmm_prim));
msgb_free(gmm_prim->oph.msg);
return -ENOTSUP;
}
/********************************
* Handling from/to upper layers:
********************************/
int gprs_gmm_prim_call_up_cb(struct osmo_gprs_gmm_prim *gmm_prim)
{
int rc;
if (g_ctx->gmm_up_cb)
rc = g_ctx->gmm_up_cb(gmm_prim, g_ctx->gmm_up_cb_user_data);
else
rc = gmm_up_cb_dummy(gmm_prim, g_ctx->gmm_up_cb_user_data);
msgb_free(gmm_prim->oph.msg);
return rc;
}
/* TS 24.007 6.6.1.1 GMMREG-Attach.request:*/
static int gprs_gmm_prim_handle_gmmreg_attach_req(struct osmo_gprs_gmm_prim *gmm_prim)
{
int rc;
rc = gprs_gmm_prim_handle_unsupported(gmm_prim);
msgb_free(gmm_prim->oph.msg);
return rc;
}
/* TS 24.007 6.6.1.4 GMMREG-Detach.request:*/
static int gprs_gmm_prim_handle_gmmreg_detach_req(struct osmo_gprs_gmm_prim *gmm_prim)
{
int rc;
rc = gprs_gmm_prim_handle_unsupported(gmm_prim);
msgb_free(gmm_prim->oph.msg);
return rc;
}
/* GMM higher layers push GMM primitive down to GMM layer: */
int osmo_gprs_gmm_prim_upper_down(struct osmo_gprs_gmm_prim *gmm_prim)
{
int rc;
OSMO_ASSERT(g_ctx);
LOGGMM(LOGL_INFO, "Rx from upper layers: %s\n", osmo_gprs_gmm_prim_name(gmm_prim));
if (gmm_prim->oph.sap != OSMO_GPRS_GMM_SAP_GMMREG)
return gprs_gmm_prim_handle_unsupported(gmm_prim);
switch (OSMO_PRIM_HDR(&gmm_prim->oph)) {
case OSMO_PRIM(OSMO_GPRS_GMM_GMMREG_ATTACH, PRIM_OP_REQUEST):
rc = gprs_gmm_prim_handle_gmmreg_attach_req(gmm_prim);
break;
case OSMO_PRIM(OSMO_GPRS_GMM_GMMREG_DETACH, PRIM_OP_REQUEST):
rc = gprs_gmm_prim_handle_gmmreg_detach_req(gmm_prim);
break;
default:
rc = gprs_gmm_prim_handle_unsupported(gmm_prim);
}
return rc;
}
/********************************
* Handling from/to lower layers:
********************************/
int gprs_gmm_prim_call_down_cb(struct osmo_gprs_gmm_prim *gmm_prim)
{
int rc;
if (g_ctx->gmm_down_cb)
rc = g_ctx->gmm_down_cb(gmm_prim, g_ctx->gmm_down_cb_user_data);
else
rc = gmm_down_cb_dummy(gmm_prim, g_ctx->gmm_down_cb_user_data);
msgb_free(gmm_prim->oph.msg);
return rc;
}
/* GMM lower layers (LLC) push GMM primitive up to GMM layer: */
int osmo_gprs_gmm_prim_lower_up(struct osmo_gprs_gmm_prim *gmm_prim)
{
OSMO_ASSERT(g_ctx);
OSMO_ASSERT(gmm_prim);
struct msgb *msg = gmm_prim->oph.msg;
int rc;
LOGGMM(LOGL_INFO, "Rx from lower layers: %s\n", osmo_gprs_gmm_prim_name(gmm_prim));
switch (gmm_prim->oph.sap) {
case OSMO_GPRS_GMM_SAP_LLGMM:
rc = gprs_gmm_prim_handle_unsupported(gmm_prim);
rc = 1;
break;
default:
rc = gprs_gmm_prim_handle_unsupported(gmm_prim);
rc = 1;
}
/* Special return value '1' means: do not free */
if (rc != 1)
msgb_free(msg);
else
rc = 0;
return rc;
}

31
src/gmm/misc.c Normal file
View File

@ -0,0 +1,31 @@
/*
* (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
* 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/licenses/>.
*
*/
#include <osmocom/core/logging.h>
#include <osmocom/core/utils.h>
#include <osmocom/gprs/gmm/gmm.h>
int g_gmm_log_cat[_OSMO_GPRS_GMM_LOGC_MAX] = { [0 ... _OSMO_GPRS_GMM_LOGC_MAX - 1] = DLGLOBAL };
void osmo_gprs_gmm_set_log_cat(enum osmo_gprs_gmm_log_cat logc, int logc_num)
{
OSMO_ASSERT(logc < _OSMO_GPRS_GMM_LOGC_MAX);
g_gmm_log_cat[logc] = logc_num;
}

View File

@ -1,4 +1,5 @@
SUBDIRS = \
gmm \
llc \
rlcmac \
sndcp \

29
tests/gmm/Makefile.am Normal file
View File

@ -0,0 +1,29 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/include/ \
$(NULL)
AM_CFLAGS = \
-Wall \
$(LIBOSMOGSM_CFLAGS) \
$(LIBOSMOCORE_CFLAGS) \
$(NULL)
AM_LDFLAGS = \
-no-install \
$(NULL)
check_PROGRAMS = \
gmm_prim_test \
$(NULL)
EXTRA_DIST = \
gmm_prim_test.err \
gmm_prim_test.ok \
$(NULL)
gmm_prim_test_SOURCES = gmm_prim_test.c
gmm_prim_test_LDADD = \
$(top_builddir)/src/gmm/libosmo-gprs-gmm.la \
$(LIBOSMOCORE_LIBS) \
$(LIBOSMOGSM_LIBS) \
$(NULL)

103
tests/gmm/gmm_prim_test.c Normal file
View File

@ -0,0 +1,103 @@
/* gmm_prim tests
*
* (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
* Author: Pau espin Pedrol <pespin@sysmocom.de>
*
* All Rights Reserved
*
* 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/licenses/>.
*
*/
#include <stdint.h>
#include <stdio.h>
#include <osmocom/core/application.h>
#include <osmocom/core/logging.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/msgb.h>
#include <osmocom/gprs/gmm/gmm.h>
#include <osmocom/gprs/gmm/gmm_prim.h>
static void *tall_ctx = NULL;
int test_gmm_prim_up_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data)
{
const char *pdu_name = osmo_gprs_gmm_prim_name(gmm_prim);
switch (gmm_prim->oph.sap) {
default:
printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
OSMO_ASSERT(0);
}
return 0;
}
int test_gmm_prim_down_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data)
{
const char *pdu_name = osmo_gprs_gmm_prim_name(gmm_prim);
switch (gmm_prim->oph.sap) {
default:
printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
OSMO_ASSERT(0);
}
return 0;
}
static void test_gmm_prim_ms(void)
{
//struct osmo_gprs_gmm_prim *gmm_prim;
int rc;
printf("==== %s() [start] ====\n", __func__);
rc = osmo_gprs_gmm_init(OSMO_GPRS_GMM_LOCATION_MS);
OSMO_ASSERT(rc == 0);
osmo_gprs_gmm_prim_set_up_cb(test_gmm_prim_up_cb, NULL);
osmo_gprs_gmm_prim_set_down_cb(test_gmm_prim_down_cb, NULL);
//gmm_prim = osmo_gprs_gmm_prim_alloc_gmmreg_attach_req();
//OSMO_ASSERT(gmm_prim);
//rc = osmo_gprs_gmm_prim_upper_down(gmm_prim);
//OSMO_ASSERT(rc == 0);
printf("==== %s() [end] ====\n", __func__);
}
static const struct log_info_cat test_log_categories[] = { };
static const struct log_info test_log_info = {
.cat = test_log_categories,
.num_cat = ARRAY_SIZE(test_log_categories),
};
int main(int argc, char *argv[])
{
tall_ctx = talloc_named_const(NULL, 1, __FILE__);
osmo_init_logging2(tall_ctx, &test_log_info);
log_parse_category_mask(osmo_stderr_target, "DLGLOBAL,1:");
log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
log_set_print_category_hex(osmo_stderr_target, 0);
log_set_print_category(osmo_stderr_target, 1);
log_set_print_level(osmo_stderr_target, 1);
log_set_use_color(osmo_stderr_target, 0);
test_gmm_prim_ms();
talloc_free(tall_ctx);
}

View File

View File

@ -0,0 +1,2 @@
==== test_gmm_prim_ms() [start] ====
==== test_gmm_prim_ms() [end] ====

View File

@ -1,6 +1,13 @@
AT_INIT
AT_BANNER([Regression tests])
AT_SETUP([gmm/gmm_prim])
AT_KEYWORDS([gmm gmm_prim])
cat $abs_srcdir/gmm/gmm_prim_test.ok > expout
cat $abs_srcdir/gmm/gmm_prim_test.err > experr
AT_CHECK([$abs_top_builddir/tests/gmm/gmm_prim_test], [0], [expout], [experr])
AT_CLEANUP
AT_SETUP([llc/llc])
AT_KEYWORDS([llc llc])
cat $abs_srcdir/llc/llc_test.ok > expout