gerrit-log
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
March 2023
- 1 participants
- 3642 discussions
pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32156 )
Change subject: Fix typo LLGM -> LLGMM
......................................................................
Fix typo LLGM -> LLGMM
The interface name is LLGMM, as presented in TS 44.06 7.1.0 and TS
24.007
Change-Id: I59577d27bedd26903c9b1bfc64792f0891cea728
---
M include/osmocom/gprs/llc/llc_prim.h
M src/gmm/gmm_prim.c
M src/llc/llc_llgmm.c
M src/llc/llc_prim.c
M tests/gmm/gmm_prim_test.c
M tests/gmm/gmm_prim_test.ok
M tests/llc/llc_prim_test.c
M tests/llc/llc_prim_test.err
8 files changed, 28 insertions(+), 16 deletions(-)
Approvals:
Jenkins Builder: Verified
laforge: Looks good to me, approved
diff --git a/include/osmocom/gprs/llc/llc_prim.h b/include/osmocom/gprs/llc/llc_prim.h
index 1a317e1..66b8a2a 100644
--- a/include/osmocom/gprs/llc/llc_prim.h
+++ b/include/osmocom/gprs/llc/llc_prim.h
@@ -12,7 +12,7 @@
/* Section 7.1.0 */
enum osmo_gprs_llc_prim_sap {
- OSMO_GPRS_LLC_SAP_LLGM,
+ OSMO_GPRS_LLC_SAP_LLGMM,
OSMO_GPRS_LLC_SAP_LL,
OSMO_GPRS_LLC_SAP_GRR,
OSMO_GPRS_LLC_SAP_BSSGP,
diff --git a/src/gmm/gmm_prim.c b/src/gmm/gmm_prim.c
index ce7afb2..9888e50 100644
--- a/src/gmm/gmm_prim.c
+++ b/src/gmm/gmm_prim.c
@@ -643,7 +643,7 @@
LOGGMM(LOGL_INFO, "Rx from lower layers: %s\n", osmo_gprs_llc_prim_name(llc_prim));
switch (llc_prim->oph.sap) {
- case OSMO_GPRS_LLC_SAP_LLGM:
+ case OSMO_GPRS_LLC_SAP_LLGMM:
rc = gprs_gmm_prim_handle_llgmm(llc_prim);
break;
case OSMO_GPRS_LLC_SAP_LL:
diff --git a/src/llc/llc_llgmm.c b/src/llc/llc_llgmm.c
index b099a6a..9797456 100644
--- a/src/llc/llc_llgmm.c
+++ b/src/llc/llc_llgmm.c
@@ -79,7 +79,7 @@
enum osmo_prim_operation operation,
unsigned int l3_len)
{
- return gprs_llc_prim_alloc(OSMO_GPRS_LLC_SAP_LLGM, type, operation, l3_len);
+ return gprs_llc_prim_alloc(OSMO_GPRS_LLC_SAP_LLGMM, type, operation, l3_len);
}
/* 7.2.1.1 LLGMM-ASSIGN.req (MS/SGSN):*/
diff --git a/src/llc/llc_prim.c b/src/llc/llc_prim.c
index fd3578e..d653f03 100644
--- a/src/llc/llc_prim.c
+++ b/src/llc/llc_prim.c
@@ -33,7 +33,7 @@
#define LLC_MSGB_HEADROOM 0
const struct value_string osmo_gprs_llc_prim_sap_names[] = {
- { OSMO_GPRS_LLC_SAP_LLGM, "LLGM" },
+ { OSMO_GPRS_LLC_SAP_LLGMM, "LLGMM" },
{ OSMO_GPRS_LLC_SAP_LL, "LL" },
{ OSMO_GPRS_LLC_SAP_GRR, "GRR" },
{ OSMO_GPRS_LLC_SAP_BSSGP, "BSSGP" },
@@ -48,7 +48,7 @@
const char *type;
switch (llc_prim->oph.sap) {
- case OSMO_GPRS_LLC_SAP_LLGM:
+ case OSMO_GPRS_LLC_SAP_LLGMM:
type = osmo_gprs_llc_llgmm_prim_type_name(llc_prim->oph.primitive);
break;
case OSMO_GPRS_LLC_SAP_LL:
@@ -157,7 +157,7 @@
LOGLLC(LOGL_INFO, "Rx from upper layers: %s\n", osmo_gprs_llc_prim_name(llc_prim));
switch (llc_prim->oph.sap) {
- case OSMO_GPRS_LLC_SAP_LLGM:
+ case OSMO_GPRS_LLC_SAP_LLGMM:
rc = gprs_llc_prim_llgmm_upper_down(llc_prim);
break;
case OSMO_GPRS_LLC_SAP_LL:
diff --git a/tests/gmm/gmm_prim_test.c b/tests/gmm/gmm_prim_test.c
index 0053b94..fa300d4 100644
--- a/tests/gmm/gmm_prim_test.c
+++ b/tests/gmm/gmm_prim_test.c
@@ -204,7 +204,7 @@
const char *pdu_name = osmo_gprs_llc_prim_name(llc_prim);
switch (llc_prim->oph.sap) {
- case OSMO_GPRS_LLC_SAP_LLGM:
+ case OSMO_GPRS_LLC_SAP_LLGMM:
printf("%s(): Rx %s TLLI=0x%08x\n", __func__, pdu_name, llc_prim->llgmm.tlli);
break;
case OSMO_GPRS_LLC_SAP_LL:
diff --git a/tests/gmm/gmm_prim_test.ok b/tests/gmm/gmm_prim_test.ok
index dbbb858..12afb40 100644
--- a/tests/gmm/gmm_prim_test.ok
+++ b/tests/gmm/gmm_prim_test.ok
@@ -2,21 +2,21 @@
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 01 04 97 07 00 00 01 0a 00 05 f4 00 00 00 00 00 f0 00 00 00 00 00 ]
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 16 08 42 32 24 43 32 24 43 f2 ]
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 13 02 ]
-test_gmm_prim_llc_down_cb(): Rx LLGM-ASSIGN.request TLLI=0x00000000
-test_gmm_prim_llc_down_cb(): Rx LLGM-ASSIGN.request TLLI=0x00000000
+test_gmm_prim_llc_down_cb(): Rx LLGMM-ASSIGN.request TLLI=0x00000000
+test_gmm_prim_llc_down_cb(): Rx LLGMM-ASSIGN.request TLLI=0x00000000
test_gmm_prim_down_cb(): Rx GMRR-ASSIGN.request new_tlli=0xea711b41
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=[08 03 ]
test_gmm_prim_up_cb(): Rx GMMREG-ATTACH.confirm accepted=1 rej_cause=0
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=[08 05 20 0a 00 05 f4 ea 71 1b 41 ]
-test_gmm_prim_llc_down_cb(): Rx LLGM-ASSIGN.request TLLI=0x00000000
+test_gmm_prim_llc_down_cb(): Rx LLGMM-ASSIGN.request TLLI=0x00000000
test_gmm_prim_up_cb(): Rx GMMREG-DETACH.confirm detach_type='GPRS detach'
==== test_gmm_prim_ms_gmmreg() [end] ====
==== test_gmm_prim_ms_gmmsm() [start] ====
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 01 04 97 07 00 00 01 0a 00 05 f4 00 00 00 00 00 f0 00 00 00 00 00 ]
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 16 08 42 32 24 43 32 24 43 f2 ]
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 13 02 ]
-test_gmm_prim_llc_down_cb(): Rx LLGM-ASSIGN.request TLLI=0x00000000
-test_gmm_prim_llc_down_cb(): Rx LLGM-ASSIGN.request TLLI=0x00000000
+test_gmm_prim_llc_down_cb(): Rx LLGMM-ASSIGN.request TLLI=0x00000000
+test_gmm_prim_llc_down_cb(): Rx LLGMM-ASSIGN.request TLLI=0x00000000
test_gmm_prim_down_cb(): Rx GMRR-ASSIGN.request new_tlli=0xea711b41
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=[08 03 ]
test_gmm_prim_up_cb(): Rx GMMSM-ESTABLISH.confirm sess_id=1234 accepted=1 rej_cause=0
diff --git a/tests/llc/llc_prim_test.c b/tests/llc/llc_prim_test.c
index 3e3dc82..83a7556 100644
--- a/tests/llc/llc_prim_test.c
+++ b/tests/llc/llc_prim_test.c
@@ -44,7 +44,7 @@
const char *pdu_name = osmo_gprs_llc_prim_name(llc_prim);
switch (llc_prim->oph.sap) {
- case OSMO_GPRS_LLC_SAP_LLGM:
+ case OSMO_GPRS_LLC_SAP_LLGMM:
printf("%s(): Rx %s TLLI=0x%08x\n", __func__, pdu_name, llc_prim->llgmm.tlli);
break;
case OSMO_GPRS_LLC_SAP_LL:
diff --git a/tests/llc/llc_prim_test.err b/tests/llc/llc_prim_test.err
index 2c38469..667b423 100644
--- a/tests/llc/llc_prim_test.err
+++ b/tests/llc/llc_prim_test.err
@@ -8,11 +8,11 @@
DLGLOBAL NOTICE LLME(ffffffff/e1c5d364){UNASSIGNED} LLC RX: unknown TLLI 0xe1c5d364, creating LLME on the fly
DLGLOBAL DEBUG LLE(ffffffff/e1c5d364,GMM){UNASSIGNED} Rx SAPI=1 (GMM), UI func=UI C/R=0 PM=0 E=0 IP=0 N(U)=0 FCS=f218e2
DLGLOBAL INFO Rx from upper layers: LL-UNITDATA.request
-DLGLOBAL INFO Rx from upper layers: LLGM-ASSIGN.request
+DLGLOBAL INFO Rx from upper layers: LLGMM-ASSIGN.request
DLGLOBAL NOTICE LLME(ffffffff/e1c5d364){UNASSIGNED} LLGM Assign pre (e1c5d364 => e1c5d364)
DLGLOBAL NOTICE LLME(e1c5d364/e1c5d364){ASSIGNED} LLGM Assign post (e1c5d364 => e1c5d364)
-DLGLOBAL INFO Rx from upper layers: LLGM-RESET.request
-DLGLOBAL INFO LLME(e1c5d364/e1c5d364){ASSIGNED} LLGM-RESET.request
+DLGLOBAL INFO Rx from upper layers: LLGMM-RESET.request
+DLGLOBAL INFO LLME(e1c5d364/e1c5d364){ASSIGNED} LLGMM-RESET.request
DLGLOBAL INFO Rx from upper layers: LL-XID.request
DLGLOBAL NOTICE LLE(e1c5d364/e1c5d364,SNDCP3){UNASSIGNED} Sending XID type L3-Params (30 bytes) request to MS...
DLGLOBAL INFO Rx from upper layers: LL-UNITDATA.request
--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32156
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I59577d27bedd26903c9b1bfc64792f0891cea728
Gerrit-Change-Number: 32156
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: merged
1
0
pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32154 )
Change subject: Introduce libosmo-gprs-sm
......................................................................
Introduce libosmo-gprs-sm
This patch itnroduces all the boilerplate required to build and package
a new libosmo-gprs-sm.so library, which aims to contain the SM layer
implementation.
A minimal implementation is provided together with a unit test,
showcasing Activation of a PDP Context and requesting implicit GPRS
attach to GMM if it is not yet attached.
This commit also adds/improves code in GMM layer implementing the GMMSM
SAP which is used to interact SM<->GMM.
Related: OS#5501
Change-Id: I9b4a9a6364f7799540475e7e1d10ab2310768281
---
M Makefile.am
M configure.ac
M contrib/libosmo-gprs.spec.in
M debian/control
A debian/libosmo-gprs-sm-dev.install
A debian/libosmo-gprs-sm0.install
M include/osmocom/gprs/Makefile.am
M include/osmocom/gprs/gmm/gmm_ms_fsm.h
M include/osmocom/gprs/gmm/gmm_prim.h
M include/osmocom/gprs/gmm/gmm_private.h
A include/osmocom/gprs/sm/Makefile.am
A include/osmocom/gprs/sm/sm.h
A include/osmocom/gprs/sm/sm_ms_fsm.h
A include/osmocom/gprs/sm/sm_pdu.h
A include/osmocom/gprs/sm/sm_prim.h
A include/osmocom/gprs/sm/sm_private.h
A libosmo-gprs-sm.pc.in
M src/Makefile.am
M src/gmm/gmm.c
M src/gmm/gmm_ms_fsm.c
M src/gmm/gmm_prim.c
A src/sm/Makefile.am
A src/sm/misc.c
A src/sm/sm.c
A src/sm/sm_ms_fsm.c
A src/sm/sm_pdu.c
A src/sm/sm_prim.c
M tests/Makefile.am
M tests/gmm/gmm_prim_test.c
M tests/gmm/gmm_prim_test.err
M tests/gmm/gmm_prim_test.ok
A tests/sm/Makefile.am
A tests/sm/sm_prim_test.c
A tests/sm/sm_prim_test.err
A tests/sm/sm_prim_test.ok
M tests/testsuite.at
36 files changed, 2,501 insertions(+), 60 deletions(-)
Approvals:
Jenkins Builder: Verified
fixeria: Looks good to me, approved
diff --git a/Makefile.am b/Makefile.am
index 4a55859..2c727b0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,6 +18,7 @@
libosmo-gprs-gmm.pc \
libosmo-gprs-llc.pc \
libosmo-gprs-rlcmac.pc \
+ libosmo-gprs-sm.pc \
libosmo-gprs-sndcp.pc \
$(NULL)
diff --git a/configure.ac b/configure.ac
index 4631b8b..52b9d14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,6 +79,7 @@
libosmo-gprs-llc.pc
libosmo-gprs-rlcmac.pc
libosmo-gprs-sndcp.pc
+ libosmo-gprs-sm.pc
include/Makefile
include/osmocom/Makefile
include/osmocom/csn1/Makefile
@@ -87,17 +88,20 @@
include/osmocom/gprs/llc/Makefile
include/osmocom/gprs/rlcmac/Makefile
include/osmocom/gprs/sndcp/Makefile
+ include/osmocom/gprs/sm/Makefile
src/Makefile
src/csn1/Makefile
src/gmm/Makefile
src/llc/Makefile
src/rlcmac/Makefile
src/sndcp/Makefile
+ src/sm/Makefile
tests/Makefile
tests/gmm/Makefile
tests/llc/Makefile
tests/rlcmac/Makefile
tests/sndcp/Makefile
+ tests/sm/Makefile
Makefile
contrib/libosmo-gprs.spec])
AC_OUTPUT
diff --git a/contrib/libosmo-gprs.spec.in b/contrib/libosmo-gprs.spec.in
index 9ad4817..ed43968 100644
--- a/contrib/libosmo-gprs.spec.in
+++ b/contrib/libosmo-gprs.spec.in
@@ -114,6 +114,24 @@
This package provides development files for compiling a program using
libosmo-gprs-sndcp - SNDCP (Subnetwork Dependent Convergence Protocol) layer for (E)GPRS.
+%package -n libosmo-gprs-sm0
+Summary: Osmocom GPRS SM library
+License: AGPL-3.0-or-later
+Group: System/Libraries
+
+%description -n libosmo-gprs-sm0
+This package provides SM (Session Management) layer for (E)GPRS.
+
+%package -n libosmo-gprs-sm-devel
+Summary: Development files for libosmo-gprs-sm
+License: AGPL-3.0-or-later
+Group: Development/Libraries/C and C++
+Requires: libosmo-gprs-sm0 = %{version}
+
+%description -n libosmo-gprs-sm-devel
+This package provides development files for compiling a program using
+libosmo-gprs-sm - SM (Session Management) layer for (E)GPRS.
+
%prep
%setup -q
@@ -140,6 +158,8 @@
%postun -n libosmo-gprs-rlcmac0 -p /sbin/ldconfig
%post -n libosmo-gprs-sndcp0 -p /sbin/ldconfig
%postun -n libosmo-gprs-sndcp0 -p /sbin/ldconfig
+%post -n libosmo-gprs-sm0 -p /sbin/ldconfig
+%postun -n libosmo-gprs-sm0 -p /sbin/ldconfig
%files -n libosmo-csn1-0
%_libdir/libosmo-csn1.so.0*
@@ -195,4 +215,15 @@
%_libdir/libosmo-gprs-sndcp.so
%_libdir/pkgconfig/libosmo-gprs-sndcp.pc
+%files -n libosmo-gprs-sm0
+%_libdir/libosmo-gprs-sm.so.0*
+
+%files -n libosmo-gprs-sm-devel
+%dir %_includedir/%name
+%dir %_includedir/%name/osmocom
+%dir %_includedir/%name/osmocom/gprs
+%_includedir/%name/osmocom/gprs/sm
+%_libdir/libosmo-gprs-sm.so
+%_libdir/pkgconfig/libosmo-gprs-sm.pc
+
%changelog
diff --git a/debian/control b/debian/control
index b2a5d5f..283ee26 100644
--- a/debian/control
+++ b/debian/control
@@ -142,3 +142,28 @@
Depends: libosmo-gprs-sndcp0 (= ${binary:Version}),
${misc:Depends}
Description: Development headers and libraries for libosmo-gprs-sndcp
+
+Package: libosmo-gprs-sm0
+Section: libs
+Architecture: any
+Multi-Arch: same
+Pre-Depends: ${misc:Pre-Depends}
+Depends: ${misc:Depends},
+ ${shlibs:Depends}
+Description: Osmocom SM (Session Management) layer for GPRS and EGPRS
+
+Package: libosmo-gprs-sm-dbg
+Architecture: any
+Section: debug
+Multi-Arch: same
+Depends: libosmo-gprs-sm0 (= ${binary:Version}),
+ ${misc:Depends}
+Description: Debug symbols for libosmo-gprs-sm
+
+Package: libosmo-gprs-sm-dev
+Architecture: any
+Multi-Arch: same
+Section: libdevel
+Depends: libosmo-gprs-sm0 (= ${binary:Version}),
+ ${misc:Depends}
+Description: Development headers and libraries for libosmo-gprs-sm
diff --git a/debian/libosmo-gprs-sm-dev.install b/debian/libosmo-gprs-sm-dev.install
new file mode 100644
index 0000000..aba99ff
--- /dev/null
+++ b/debian/libosmo-gprs-sm-dev.install
@@ -0,0 +1,5 @@
+usr/include/osmocom/gprs/sm
+usr/lib/*/libosmo-gprs-sm*.a
+usr/lib/*/libosmo-gprs-sm*.so
+usr/lib/*/libosmo-gprs-sm*.la
+usr/lib/*/pkgconfig/libosmo-gprs-sm.pc
diff --git a/debian/libosmo-gprs-sm0.install b/debian/libosmo-gprs-sm0.install
new file mode 100644
index 0000000..a15113e
--- /dev/null
+++ b/debian/libosmo-gprs-sm0.install
@@ -0,0 +1 @@
+usr/lib/*/libosmo-gprs-sm*.so.*
diff --git a/include/osmocom/gprs/Makefile.am b/include/osmocom/gprs/Makefile.am
index bb6c242..3b860c6 100644
--- a/include/osmocom/gprs/Makefile.am
+++ b/include/osmocom/gprs/Makefile.am
@@ -3,4 +3,5 @@
llc \
rlcmac \
sndcp \
+ sm \
$(NULL)
diff --git a/include/osmocom/gprs/gmm/gmm_ms_fsm.h b/include/osmocom/gprs/gmm/gmm_ms_fsm.h
index dd22a32..3e6ac96 100644
--- a/include/osmocom/gprs/gmm/gmm_ms_fsm.h
+++ b/include/osmocom/gprs/gmm/gmm_ms_fsm.h
@@ -30,7 +30,7 @@
GPRS_GMM_MS_EV_ATTACH_REQUESTED,
GPRS_GMM_MS_EV_ATTACH_REJECTED,
GPRS_GMM_MS_EV_ATTACH_ACCEPTED,
- GPRS_GMM_MS_EV_DETACH_REQUESTED, /* also network initiated. data: ptr to enum osmo_gprs_gmm_detach_ms_type */
+ GPRS_GMM_MS_EV_DETACH_REQUESTED, /* also network initiated. */
GPRS_GMM_MS_EV_DETACH_REQUESTED_POWEROFF,
GPRS_GMM_MS_EV_DETACH_ACCEPTED,
GPRS_GMM_MS_EV_SR_REQUESTED, /* (Iu only) */
@@ -45,8 +45,23 @@
struct gprs_gmm_ms_fsm_ctx {
struct osmo_fsm_inst *fi;
struct gprs_gmm_entity *gmme;
- /* Type of last initiated detach: */
- enum osmo_gprs_gmm_detach_ms_type detach_type;
+
+ /* Info about last initiated attach: */
+ struct {
+ enum osmo_gprs_gmm_attach_type type;
+ bool with_imsi;
+ bool explicit_att; /* true if by SMREG-ATTACH.req requested it */
+ bool implicit_att; /* true if GMMSM-ESTABLISH.req requested it */
+ /* Session Ids waiting for attach to happen during implicit_att: */
+ uint32_t sess_id[16];
+ uint8_t num_sess_id;
+ } attach;
+
+ /* Info about last initiated detach: */
+ struct {
+ enum osmo_gprs_gmm_detach_ms_type type;
+ enum osmo_gprs_gmm_detach_poweroff_type poweroff_type;
+ } detach;
};
int gprs_gmm_ms_fsm_init(void);
@@ -54,3 +69,14 @@
int gprs_gmm_ms_fsm_ctx_init(struct gprs_gmm_ms_fsm_ctx *ctx, struct gprs_gmm_entity *gmme);
void gprs_gmm_ms_fsm_ctx_release(struct gprs_gmm_ms_fsm_ctx *ctx);
+
+int gprs_gmm_ms_fsm_ctx_request_attach(struct gprs_gmm_ms_fsm_ctx *ctx,
+ enum osmo_gprs_gmm_attach_type attach_type,
+ bool attach_with_imsi,
+ bool explicit_attach,
+ uint32_t sess_id);
+
+int gprs_gmm_ms_fsm_ctx_request_detach(struct gprs_gmm_ms_fsm_ctx *ctx,
+ enum osmo_gprs_gmm_detach_ms_type detach_type,
+ enum osmo_gprs_gmm_detach_poweroff_type poweroff_type);
+
diff --git a/include/osmocom/gprs/gmm/gmm_prim.h b/include/osmocom/gprs/gmm/gmm_prim.h
index 16cd712..78c8dfb 100644
--- a/include/osmocom/gprs/gmm/gmm_prim.h
+++ b/include/osmocom/gprs/gmm/gmm_prim.h
@@ -184,14 +184,30 @@
/* Parameters for OSMO_GPRS_GMM_GMMSM_* prims
*/
struct osmo_gprs_gmm_gmmsm_prim {
- /* Common fields (none) */
+ /* Common fields */
+ uint32_t sess_id;
union {
/* OSMO_GPRS_GMM_GMMSM_ESTABLISH | Req */
struct {
+ enum osmo_gprs_gmm_attach_type attach_type;
+ uint32_t ptmsi;
+ bool attach_with_imsi;
+ char imsi[OSMO_IMSI_BUF_SIZE];
+ char imei[GSM23003_IMEI_NUM_DIGITS + 1];
+ char imeisv[GSM23003_IMEISV_NUM_DIGITS+1];
+ /* attach-type, READY-timer, STANDBY-timer */
} establish_req;
/* OSMO_GPRS_GMM_GMMSM_ESTABLISH | Cnf/Rej */
struct {
- uint8_t cause;
+ bool accepted;
+ union {
+ struct {
+ /* PLMNs MT-caps, attach-type. */
+ } acc;
+ struct {
+ uint8_t cause;
+ } rej;
+ };
} establish_cnf;
/* OSMO_GPRS_GMM_GMMSM_RELEASE | Ind */
struct {
@@ -242,5 +258,5 @@
struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmrr_page_ind(uint32_t tlli);
/* Alloc primitive for GMMSM SAP: */
-struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmsm_establish_req(void);
-struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmsm_unitdata_req(uint8_t *smpdu, unsigned int smpdu_len);
+struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmsm_establish_req(uint32_t id);
+struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmsm_unitdata_req(uint32_t id, uint8_t *smpdu, unsigned int smpdu_len);
diff --git a/include/osmocom/gprs/gmm/gmm_private.h b/include/osmocom/gprs/gmm/gmm_private.h
index 0f05dff..2f6eb8c 100644
--- a/include/osmocom/gprs/gmm/gmm_private.h
+++ b/include/osmocom/gprs/gmm/gmm_private.h
@@ -77,9 +77,9 @@
struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmrr_assign_req(uint32_t new_tlli);
-struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_establish_cnf(uint8_t cause);
-struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmrr_release_ind(void);
-struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_unitdata_ind(uint8_t *smpdu, unsigned int smpdu_len);
+struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_establish_cnf(uint32_t id, uint8_t cause);
+struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmrr_release_ind(uint32_t id);
+struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_unitdata_ind(uint32_t id, uint8_t *smpdu, unsigned int smpdu_len);
/* gmm.c: */
struct gprs_gmm_entity *gprs_gmm_gmme_alloc(void);
@@ -93,6 +93,9 @@
enum osmo_gprs_gmm_detach_ms_type detach_type,
enum osmo_gprs_gmm_detach_poweroff_type poweroff_type);
+int gprs_gmm_submit_gmmreg_attach_cnf(struct gprs_gmm_entity *gmme, bool accepted, uint8_t cause);
+int gprs_gmm_submit_gmmsm_establish_cnf(struct gprs_gmm_entity *gmme, uint32_t sess_id, bool accepted, uint8_t cause);
+
#define LOGGMME(snme, level, fmt, args...) \
LOGGMM(level, "GMME(PTMSI-%08x) " fmt, \
gmme->ptmsi, \
diff --git a/include/osmocom/gprs/sm/Makefile.am b/include/osmocom/gprs/sm/Makefile.am
new file mode 100644
index 0000000..46a30cb
--- /dev/null
+++ b/include/osmocom/gprs/sm/Makefile.am
@@ -0,0 +1,13 @@
+
+noinst_HEADERS = \
+ sm_ms_fsm.h \
+ sm_pdu.h \
+ sm_private.h \
+ $(NULL)
+
+sm_HEADERS = \
+ sm.h \
+ sm_prim.h \
+ $(NULL)
+
+smdir = $(includedir)/osmocom/gprs/sm
diff --git a/include/osmocom/gprs/sm/sm.h b/include/osmocom/gprs/sm/sm.h
new file mode 100644
index 0000000..37f86bc
--- /dev/null
+++ b/include/osmocom/gprs/sm/sm.h
@@ -0,0 +1,54 @@
+#pragma once
+
+/* GPRS Session Management (SM) definitions from 3GPP TS 24.008 */
+
+#include <stdint.h>
+#include <stddef.h>
+
+/* 3GPP TS 24.008 10.5.6.1 */
+#define OSMO_GPRS_SM_APN_MAXLEN 100
+
+/* Max number of NSAPI */
+#define OSMO_GPRS_SM_PDP_MAXNSAPI 16
+
+/* 3GPP TS 24.008 10.5.6.3 Protocol configuration options */
+#define OSMO_GPRS_SM_PCO_MAXLEN 253
+
+/* 3GPP TS 24.008 10.5.6.5 Quality of service */
+#define OSMO_GPRS_SM_QOS_MAXLEN 22
+
+/* 3GPP TS 24.008 10.5.6.21 NBIFOM container (T=1,L=1,V=255 => 257) */
+#define OSMO_GPRS_SM_MBIFORM_MAXLEN 255
+
+/* TS 24.008 10.5.6.9 "LLC service access point identifier" */
+enum osmo_gprs_sm_llc_sapi {
+ OSMO_GPRS_SM_LLC_SAPI_UNASSIGNED = 0,
+ OSMO_GPRS_SM_LLC_SAPI_SAPI3 = 3,
+ OSMO_GPRS_SM_LLC_SAPI_SAPI5 = 5,
+ OSMO_GPRS_SM_LLC_SAPI_SAPI9 = 9,
+ OSMO_GPRS_SM_LLC_SAPI_SAPI11 = 11,
+};
+
+/* 10.5.6.4 Packet data protocol address */
+enum osmo_gprs_sm_pdp_addr_ietf_type {
+ OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4 = 0x21, /* used in earlier version of this protocol */
+ OSMO_GPRS_SM_PDP_ADDR_IETF_IPV6 = 0x57,
+ OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4V6 = 0x8D,
+ /* All other values shall be interpreted as IPv4 address in this version of the protocol */
+};
+
+/* Use stack as MS or as network? */
+enum osmo_gprs_sm_location {
+ OSMO_GPRS_SM_LOCATION_UNSET,
+ OSMO_GPRS_SM_LOCATION_MS,
+ OSMO_GPRS_SM_LOCATION_NETWORK,
+};
+
+int osmo_gprs_sm_init(enum osmo_gprs_sm_location location);
+
+enum osmo_gprs_sm_log_cat {
+ OSMO_GPRS_SM_LOGC_SM,
+ _OSMO_GPRS_SM_LOGC_MAX,
+};
+
+void osmo_gprs_sm_set_log_cat(enum osmo_gprs_sm_log_cat logc, int logc_num);
diff --git a/include/osmocom/gprs/sm/sm_ms_fsm.h b/include/osmocom/gprs/sm/sm_ms_fsm.h
new file mode 100644
index 0000000..3970d73
--- /dev/null
+++ b/include/osmocom/gprs/sm/sm_ms_fsm.h
@@ -0,0 +1,44 @@
+#pragma once
+
+#include <osmocom/core/fsm.h>
+#include <osmocom/gprs/sm/sm_prim.h>
+
+struct gprs_sm_entity;
+
+/* 3GPP TS 24.008 § 6.1.2.1 Session management states in the MS */
+enum gprs_sm_ms_fsm_states {
+ GPRS_SM_MS_ST_PDP_INACTIVE, /* 6.1.2.1.1 */
+ GPRS_SM_MS_ST_PDP_ACTIVE_PENDING, /* 6.1.2.1.2 */
+ GPRS_SM_MS_ST_PDP_ACTIVE, /* 6.1.2.1.4 */
+ GPRS_SM_MS_ST_PDP_MODIFY_PENDING, /* 6.1.2.1.5 */
+ GPRS_SM_MS_ST_PDP_INACTIVE_PENDING, /* 6.1.2.1.3 */
+ //GPRS_SM_MS_ST_MBMS_ACTIVE_PENDING, /* 6.1.2.1.6 */
+ //GPRS_SM_MS_ST_MBMS_ACTIVE, /* 6.1.2.1.7 */
+};
+
+enum gprs_sm_ms_fsm_events {
+ GPRS_SM_MS_EV_RX_GMM_ESTABLISH_CNF,
+ GPRS_SM_MS_EV_RX_GMM_ESTABLISH_REJ,
+ GPRS_SM_MS_EV_TX_ACT_PDP_CTX_REQ,
+ GPRS_SM_MS_EV_RX_ACT_PDP_CTX_REJ, /* data: enum gsm48_gsm_cause *cause */
+ GPRS_SM_MS_EV_RX_ACT_PDP_CTX_ACC,
+ GPRS_SM_MS_EV_TX_DEACT_PDP_CTX_REQ,
+ GPRS_SM_MS_EV_RX_DEACT_PDP_CTX_REQ,
+ GPRS_SM_MS_EV_RX_DEACT_PDP_CTX_ACC,
+ GPRS_SM_MS_EV_TX_MOD_PDP_CTX_REQ,
+ GPRS_SM_MS_EV_RX_MOD_PDP_CTX_REJ,
+ GPRS_SM_MS_EV_RX_MOD_PDP_CTX_ACC,
+};
+
+struct gprs_sm_ms_fsm_ctx {
+ struct osmo_fsm_inst *fi;
+ struct gprs_sm_entity *sme;
+ /* TS 24.008 6.1.3.1.5 retrans counter for T3380: */
+ uint8_t act_pdp_ctx_attempts;
+};
+
+int gprs_sm_ms_fsm_init(void);
+void gprs_sm_ms_fsm_set_log_cat(int logcat);
+
+int gprs_sm_ms_fsm_ctx_init(struct gprs_sm_ms_fsm_ctx *ctx, struct gprs_sm_entity *sme);
+void gprs_sm_ms_fsm_ctx_release(struct gprs_sm_ms_fsm_ctx *ctx);
diff --git a/include/osmocom/gprs/sm/sm_pdu.h b/include/osmocom/gprs/sm/sm_pdu.h
new file mode 100644
index 0000000..50e3ae9
--- /dev/null
+++ b/include/osmocom/gprs/sm/sm_pdu.h
@@ -0,0 +1,17 @@
+/* GMM PDUs, 3GPP TS 9.5 24.008 GPRS Session Management Messages */
+#pragma once
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
+
+struct gprs_gmm_entity;
+
+#define GPRS_SM_ALLOC_SIZE 2048
+#define GPRS_SM_ALLOC_HEADROOM 256
+
+extern const struct tlv_definition gprs_sm_att_tlvdef;
+#define gprs_sm_tlv_parse(dec, buf, len) \
+ tlv_parse(dec, &gprs_sm_att_tlvdef, buf, len, 0, 0)
+
+int gprs_sm_build_act_pdp_ctx_req(struct gprs_sm_entity *sme,
+ struct msgb *msg);
diff --git a/include/osmocom/gprs/sm/sm_prim.h b/include/osmocom/gprs/sm/sm_prim.h
new file mode 100644
index 0000000..57fc32e
--- /dev/null
+++ b/include/osmocom/gprs/sm/sm_prim.h
@@ -0,0 +1,207 @@
+#pragma once
+
+/* 3GPP TS 24.007:
+ * section 6.5 "Session Management 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 SM for GPRS services"
+ */
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include <osmocom/core/utils.h>
+#include <osmocom/core/prim.h>
+#include <osmocom/core/socket.h>
+#include <osmocom/gsm/protocol/gsm_23_003.h>
+
+#include <osmocom/gprs/sm/sm.h>
+
+
+struct osmo_gprs_gmm_prim;
+
+/* 3GPP TS 24.007 */
+enum osmo_gprs_sm_prim_sap {
+ OSMO_GPRS_SM_SAP_SMREG, /* 6.5.1 */
+};
+extern const struct value_string osmo_gprs_sm_prim_sap_names[];
+static inline const char *osmo_gprs_sm_prim_sap_name(enum osmo_gprs_sm_prim_sap val)
+{
+ return get_value_string(osmo_gprs_sm_prim_sap_names, val);
+}
+
+/* 3GPP TS 24.007 Section 6.6 Registration Services for GPRS-Services */
+enum osmo_gprs_sm_smreg_prim_type {
+ OSMO_GPRS_SM_SMREG_PDP_ACTIVATE, /* Req/Cnf/Rej/Ind/Rsp */
+ OSMO_GPRS_SM_SMREG_PDP_DEACTIVATE, /* Req/Cnf/Ind */
+ OSMO_GPRS_SM_SMREG_PDP_MODIFY, /* Req/Ind/Cnf/Rej */
+ OSMO_GPRS_SM_SMREG_PDP_ACTIVATE_SEC, /* Req/Cnf/Rej */
+ OSMO_GPRS_SM_SMREG_MBMS_ACTIVATE, /* Req/Cnf/Rej/Ind */
+};
+extern const struct value_string osmo_gprs_sm_smreg_prim_type_names[];
+static inline const char *osmo_gprs_sm_smreg_prim_type_name(enum osmo_gprs_sm_smreg_prim_type val)
+{
+ return get_value_string(osmo_gprs_sm_smreg_prim_type_names, val);
+}
+
+/* Parameters for OSMO_GPRS_SM_SMREG_* prims */
+struct osmo_gprs_sm_smreg_prim {
+ /* Common fields */
+ uint32_t ms_id;
+ /* Specific fields */
+ union {
+ /* OSMO_GPRS_SM_SMREG_PDP_ACTIVATE | Req, 6.5.1.1 */
+ struct {
+ uint8_t nsapi;
+ enum osmo_gprs_sm_llc_sapi llc_sapi;
+ enum osmo_gprs_sm_pdp_addr_ietf_type pdp_addr_ietf_type;
+ struct osmo_sockaddr pdp_addr_v4;
+ struct osmo_sockaddr pdp_addr_v6;
+ uint8_t qos[OSMO_GPRS_SM_QOS_MAXLEN];
+ uint8_t qos_len;
+ char apn[OSMO_GPRS_SM_APN_MAXLEN];
+ uint8_t pco[OSMO_GPRS_SM_PCO_MAXLEN];
+ uint8_t pco_len;
+ struct {
+ uint32_t ptmsi;
+ bool attach_with_imsi;
+ char imsi[OSMO_IMSI_BUF_SIZE];
+ char imei[GSM23003_IMEI_NUM_DIGITS + 1];
+ char imeisv[GSM23003_IMEISV_NUM_DIGITS+1];
+ } gmm;
+ } pdp_act_req;
+
+ /* OSMO_GPRS_SM_SMREG_PDP_ACTIVATE | Cnf 6.5.1.2 / Rej 6.5.1.3 */
+ struct {
+ bool accepted;
+ uint8_t nsapi;
+ uint8_t pco[OSMO_GPRS_SM_PCO_MAXLEN];
+ uint8_t pco_len;
+ union {
+ struct {
+ struct osmo_sockaddr pdp_addr;
+ uint8_t qos[OSMO_GPRS_SM_QOS_MAXLEN];
+ uint8_t qos_len;
+ } acc;
+ struct {
+ uint8_t cause;
+ } rej;
+ };
+ } pdp_act_cnf;
+
+ /* OSMO_GPRS_SM_SMREG_PDP_ACTIVATE | Ind, 6.5.1.4 */
+ struct {
+ struct osmo_sockaddr pdp_addr;
+ char apn[OSMO_GPRS_SM_APN_MAXLEN];
+ uint8_t pco[OSMO_GPRS_SM_PCO_MAXLEN];
+ uint8_t pco_len;
+ } pdp_act_ind;
+
+ /* OSMO_GPRS_SM_SMREG_PDP_ACTIVATE | Rsp, 6.5.1.14 */
+ struct {
+ uint8_t cause;
+ struct osmo_sockaddr pdp_addr;
+ char apn[OSMO_GPRS_SM_APN_MAXLEN];
+ uint8_t pco[OSMO_GPRS_SM_PCO_MAXLEN];
+ uint8_t pco_len;
+ /* TODO: MBMS protocol configuration options*/
+ } pdp_act_rej_rsp;
+
+ /* OSMO_GPRS_SM_SMREG_PDP_DEACTIVATE, 6.5.1.5 */
+ struct {
+ uint8_t nsapi[OSMO_GPRS_SM_PDP_MAXNSAPI];
+ uint8_t num_nsapi;
+ uint8_t tear_down_ind;
+ uint8_t cause;
+ uint8_t pco[OSMO_GPRS_SM_PCO_MAXLEN];
+ uint8_t pco_len;
+ /* TODO: MBMS protocol configuration options*/
+ } deact_req;
+
+
+ /* OSMO_GPRS_SM_SMREG_PDP_DEACTIVATE | Cnf, 6.5.1.6 */
+ struct {
+ uint8_t nsapi[OSMO_GPRS_SM_PDP_MAXNSAPI];
+ uint8_t num_nsapi;
+ uint8_t pco[OSMO_GPRS_SM_PCO_MAXLEN];
+ uint8_t pco_len;
+ /* TODO: MBMS protocol configuration options*/
+ } deact_cnf;
+
+ /* OSMO_GPRS_SM_SMREG_PDP_DEACTIVATE | Ind, 6.5.1.7 */
+ struct {
+ uint8_t nsapi[OSMO_GPRS_SM_PDP_MAXNSAPI];
+ uint8_t num_nsapi;
+ uint8_t tear_down_ind;
+ uint8_t cause;
+ uint8_t pco[OSMO_GPRS_SM_PCO_MAXLEN];
+ uint8_t pco_len;
+ /* TODO: MBMS protocol configuration options */
+ } deact_ind;
+
+ /* OSMO_GPRS_SM_SMREG_PDP_MODIFY | Ind, 6.5.1.8 */
+ struct {
+ uint8_t qos[OSMO_GPRS_SM_QOS_MAXLEN];
+ uint8_t qos_len;
+ uint8_t nsapi;
+ uint8_t pco[OSMO_GPRS_SM_PCO_MAXLEN];
+ uint8_t pco_len;
+ } pdp_mod_ind;
+
+ /* OSMO_GPRS_SM_SMREG_PDP_MODIFY | Req 6.5.1.18 */
+ struct {
+ uint8_t qos[OSMO_GPRS_SM_QOS_MAXLEN];
+ uint8_t qos_len;
+ uint8_t nsapi;
+ uint8_t tft; /* TODO */
+ uint8_t pco[OSMO_GPRS_SM_PCO_MAXLEN];
+ uint8_t pco_len;
+ } pdp_mod_req;
+
+ /* OSMO_GPRS_SM_SMREG_PDP_MODIFY | Cnf 6.5.1.19 / Rej 6.5.1.20 */
+ struct {
+ bool accepted;
+ uint8_t nsapi;
+ uint8_t pco[OSMO_GPRS_SM_PCO_MAXLEN];
+ union {
+ struct {
+ uint8_t qos[OSMO_GPRS_SM_QOS_MAXLEN];
+ uint8_t qos_len;
+ } acc;
+ struct {
+ uint8_t cause;
+ } rej;
+ };
+ } pdp_mod_cnf;
+
+ /* TODO:
+ * OSMO_GPRS_SM_SMREG_PDP_ACTIVATE_SEC
+ * OSMO_GPRS_SM_SMREG_MBMS_ACTIVATE
+ */
+ };
+};
+
+
+struct osmo_gprs_sm_prim {
+ struct osmo_prim_hdr oph;
+ union {
+ struct osmo_gprs_sm_smreg_prim smreg;
+ };
+};
+
+typedef int (*osmo_gprs_sm_prim_up_cb)(struct osmo_gprs_sm_prim *sm_prim, void *up_user_data);
+void osmo_gprs_sm_prim_set_up_cb(osmo_gprs_sm_prim_up_cb up_cb, void *up_user_data);
+
+typedef int (*osmo_gprs_sm_prim_down_cb)(struct osmo_gprs_sm_prim *sm_prim, void *down_user_data);
+void osmo_gprs_sm_prim_set_down_cb(osmo_gprs_sm_prim_down_cb down_cb, void *down_user_data);
+
+typedef int (*osmo_gprs_sm_prim_gmm_down_cb)(struct osmo_gprs_gmm_prim *gmm_prim, void *gmm_down_user_data);
+void osmo_gprs_sm_prim_set_gmm_down_cb(osmo_gprs_sm_prim_gmm_down_cb gmm_down_cb, void *gmm_down_user_data);
+
+int osmo_gprs_sm_prim_upper_down(struct osmo_gprs_sm_prim *sm_prim);
+int osmo_gprs_sm_prim_lower_up(struct osmo_gprs_sm_prim *sm_prim);
+int osmo_gprs_sm_prim_gmm_lower_up(struct osmo_gprs_gmm_prim *gmm_prim);
+
+const char *osmo_gprs_sm_prim_name(const struct osmo_gprs_sm_prim *sm_prim);
+
+/* Alloc primitive for SMREG SAP: */
+struct osmo_gprs_sm_prim *osmo_gprs_sm_prim_alloc_smreg_pdp_act_req(void);
diff --git a/include/osmocom/gprs/sm/sm_private.h b/include/osmocom/gprs/sm/sm_private.h
new file mode 100644
index 0000000..b0043e6
--- /dev/null
+++ b/include/osmocom/gprs/sm/sm_private.h
@@ -0,0 +1,180 @@
+#pragma once
+
+/* 3GPP TS 24.007, private header */
+
+#include <stdint.h>
+#include <stddef.h>
+#include <stdbool.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/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
+
+#include <osmocom/gprs/gmm/gmm_prim.h>
+#include <osmocom/gprs/sm/sm.h>
+#include <osmocom/gprs/sm/sm_prim.h>
+#include <osmocom/gprs/sm/sm_ms_fsm.h>
+
+extern int g_sm_log_cat[_OSMO_GPRS_SM_LOGC_MAX];
+
+#define LOGSM(lvl, fmt, args...) LOGP(g_sm_log_cat[OSMO_GPRS_SM_LOGC_SM], lvl, fmt, ## args)
+
+#define msgb_sm_prim(msg) ((struct osmo_gprs_sm_prim *)(msg)->l1h)
+
+/* 10.5.6.4 Packet data protocol address */
+enum gprs_sm_pdp_addr_org {
+ GPRS_SM_PDP_ADDR_ORG_ETSI = 0x00,
+ GPRS_SM_PDP_ADDR_ORG_IETF = 0x01,
+ GPRS_SM_PDP_ADDR_ORG_EMPTY = 0x0f,
+ /* All other values are reserved. */
+};
+
+/* 10.5.6.4 Packet data protocol address */
+enum gprs_sm_pdp_addr_etsi_type {
+ GPRS_SM_PDP_ADDR_ETSI_RESERVED = 00, /* used in earlier version of this protocol */
+ GPRS_SM_PDP_ADDR_ETSI_PPP = 0x01,
+ GPRS_SM_PDP_ADDR_ETSI_NON_IP = 0x02,
+ /* All other values are reserved in this version of the protocol. */
+};
+
+struct gprs_sm_pdp_addr {
+#if OSMO_IS_LITTLE_ENDIAN
+ uint8_t spare:4,
+ organization:4; /* enum gprs_sm_pdp_addr_org */
+ uint8_t type; /* osmo_gprs_sm_pdp_addr_{etsi,ietf}_type */
+ union {
+ /* IPv4 */
+ uint32_t addr;
+
+ /* IPv6 */
+ uint8_t addr6[16];
+
+ /* IPv4v6 */
+#elif OSMO_IS_BIG_ENDIAN
+/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */
+ uint8_t organization:4, spare:4;
+ uint8_t type;
+ union {
+ uint32_t addr;
+ uint8_t addr6[16];
+#endif
+ struct {
+ uint32_t addr;
+ uint8_t addr6[16];
+ } __attribute__ ((packed)) both;
+ };
+} __attribute__ ((packed));
+
+struct gprs_sm_ms;
+
+struct gprs_sm_ctx {
+ enum osmo_gprs_sm_location location;
+ osmo_gprs_sm_prim_up_cb sm_up_cb;
+ void *sm_up_cb_user_data;
+
+ osmo_gprs_sm_prim_down_cb sm_down_cb;
+ void *sm_down_cb_user_data;
+
+ osmo_gprs_sm_prim_gmm_down_cb sm_gmm_down_cb;
+ void *sm_gmm_down_cb_user_data;
+
+ struct osmo_tdef *T_defs; /* timers controlled by SM layer */
+
+ struct llist_head ms_list; /* list of struct gprs_sm_ms->list */
+
+ uint32_t next_sess_id;
+};
+
+extern struct gprs_sm_ctx *g_ctx;
+
+/* SM Entity, PDP CTX */
+struct gprs_sm_entity {
+ struct gprs_sm_ms *ms; /* backpointer */
+
+ uint32_t sess_id;
+
+ uint8_t nsapi;
+ enum osmo_gprs_sm_llc_sapi llc_sapi;
+
+ enum osmo_gprs_sm_pdp_addr_ietf_type pdp_addr_ietf_type;
+ struct osmo_sockaddr pdp_addr_v4;
+ struct osmo_sockaddr pdp_addr_v6;
+
+ uint8_t qos[OSMO_GPRS_SM_QOS_MAXLEN];
+ uint8_t qos_len;
+
+ char apn[OSMO_GPRS_SM_APN_MAXLEN];
+
+ uint8_t pco[OSMO_GPRS_SM_MBIFORM_MAXLEN];
+ uint8_t pco_len;
+
+ uint8_t ti; /* transaction identifier */
+
+ struct gprs_sm_ms_fsm_ctx ms_fsm;
+};
+
+/* Mobile Station: */
+struct gprs_sm_ms {
+ struct llist_head list; /* item in (struct gprs_sm_ctx)->ms_list */
+
+ uint32_t ms_id;
+
+ struct gprs_sm_entity *pdp[OSMO_GPRS_SM_PDP_MAXNSAPI];
+
+ struct {
+ uint32_t ptmsi;
+ char imsi[OSMO_IMSI_BUF_SIZE];
+ char imei[GSM23003_IMEI_NUM_DIGITS + 1];
+ char imeisv[GSM23003_IMEISV_NUM_DIGITS+1];
+ } gmm;
+};
+
+/* 10.5.6.2 Network service access point identifier */
+static inline bool gprs_sm_nsapi_is_valid(uint8_t nsapi)
+{
+ return nsapi >= 5 && nsapi <= 15;
+}
+
+static inline struct gprs_sm_entity *gprs_sm_ms_get_pdp_ctx(struct gprs_sm_ms *ms,
+ uint8_t nsapi) {
+ OSMO_ASSERT(gprs_sm_nsapi_is_valid(nsapi));
+ return ms->pdp[nsapi];
+}
+
+/* sm_prim.c: */
+int gprs_sm_prim_call_up_cb(struct osmo_gprs_sm_prim *sm_prim);
+int gprs_sm_prim_call_down_cb(struct osmo_gprs_sm_prim *sm_prim);
+int gprs_sm_prim_call_gmm_down_cb(struct osmo_gprs_gmm_prim *gmm_prim);
+
+struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_act_cnf(void);
+struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_act_ind(void);
+
+/* sm.c: */
+struct gprs_sm_ms *gprs_sm_ms_alloc(uint32_t ms_id);
+void gprs_sm_ms_free(struct gprs_sm_ms *ms);
+struct gprs_sm_ms *gprs_sm_find_ms_by_id(uint32_t ms_id);
+
+struct gprs_sm_entity *gprs_sm_entity_alloc(struct gprs_sm_ms *ms, uint32_t nsapi);
+void gprs_sm_entity_free(struct gprs_sm_entity *sme);
+struct gprs_sm_entity *gprs_sm_find_sme_by_sess_id(uint32_t sess_id);
+
+int gprs_sm_submit_gmmsm_assign_req(const struct gprs_sm_entity *sme);
+int gprs_sm_submit_smreg_pdp_act_cnf(const struct gprs_sm_entity *sme, enum gsm48_gsm_cause cause);
+int gprs_sm_tx_act_pdp_ctx_req(struct gprs_sm_entity *sme);
+int gprs_sm_rx(struct gprs_sm_entity *sme, struct gsm48_hdr *gh, unsigned int len);
+
+
+#define LOGMS(snme, level, fmt, args...) \
+ LOGSM(level, "MS(ID-%u) " fmt, \
+ ms->ms_id, \
+ ## args)
+
+#define LOGSME(sme, level, fmt, args...) \
+ LOGSM(level, "PDP(ID-%u:NSAPI-%u) " fmt, \
+ sme->ms->ms_id, \
+ sme->nsapi, \
+ ## args)
diff --git a/libosmo-gprs-sm.pc.in b/libosmo-gprs-sm.pc.in
new file mode 100644
index 0000000..85158f1
--- /dev/null
+++ b/libosmo-gprs-sm.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: Osmocom [E]GPRS SM (Session Management) Library
+Description: C Utility Library
+Version: @VERSION@
+Requires: libosmo-gprs-gmm libosmocore
+Libs: -L${libdir} -losmo-gprs-sm
+Libs.private: -ltalloc
+Cflags: -I${includedir}/
diff --git a/src/Makefile.am b/src/Makefile.am
index b0b95ff..69ce5a0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,4 +4,5 @@
rlcmac \
sndcp \
gmm \
+ sm \
$(NULL)
diff --git a/src/gmm/gmm.c b/src/gmm/gmm.c
index a8b8362..ed7b69f 100644
--- a/src/gmm/gmm.c
+++ b/src/gmm/gmm.c
@@ -176,7 +176,7 @@
return NULL;
}
-static int gprs_gmm_submit_gmmreg_attach_cnf(struct gprs_gmm_entity *gmme, bool accepted, uint8_t cause)
+int gprs_gmm_submit_gmmreg_attach_cnf(struct gprs_gmm_entity *gmme, bool accepted, uint8_t cause)
{
struct osmo_gprs_gmm_prim *gmm_prim_tx;
int rc;
@@ -196,7 +196,18 @@
int rc;
gmm_prim_tx = gprs_gmm_prim_alloc_gmmreg_detach_cnf();
- gmm_prim_tx->gmmreg.detach_cnf.detach_type = gmme->ms_fsm.detach_type;
+ gmm_prim_tx->gmmreg.detach_cnf.detach_type = gmme->ms_fsm.detach.type;
+
+ rc = gprs_gmm_prim_call_up_cb(gmm_prim_tx);
+ return rc;
+}
+
+int gprs_gmm_submit_gmmsm_establish_cnf(struct gprs_gmm_entity *gmme, uint32_t sess_id, bool accepted, uint8_t cause)
+{
+ struct osmo_gprs_gmm_prim *gmm_prim_tx;
+ int rc;
+
+ gmm_prim_tx = gprs_gmm_prim_alloc_gmmsm_establish_cnf(sess_id, cause);
rc = gprs_gmm_prim_call_up_cb(gmm_prim_tx);
return rc;
@@ -435,11 +446,6 @@
}
}
- /* Submit GMMREG-ATTACH-CNF as per TS 24.007 Annex C.1 */
- rc = gprs_gmm_submit_gmmreg_attach_cnf(gmme, true, 0);
- if (rc < 0)
- goto rejected;
-
/* Submit LLGMM-ASSIGN-REQ as per TS 24.007 Annex C.1 */
rc = gprs_gmm_submit_llgmm_assing_req(gmme);
if (rc < 0)
diff --git a/src/gmm/gmm_ms_fsm.c b/src/gmm/gmm_ms_fsm.c
index 423d1d0..cdc2089 100644
--- a/src/gmm/gmm_ms_fsm.c
+++ b/src/gmm/gmm_ms_fsm.c
@@ -44,13 +44,28 @@
}
}
+static void st_gmm_ms_deregistered_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gprs_gmm_ms_fsm_ctx *ctx = (struct gprs_gmm_ms_fsm_ctx *)fi->priv;
+
+ memset(&ctx->attach, 0, sizeof(ctx->attach));
+}
+
static void st_gmm_ms_deregistered(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
+ struct gprs_gmm_ms_fsm_ctx *ctx = (struct gprs_gmm_ms_fsm_ctx *)fi->priv;
+ int rc;
+
switch (event) {
case GPRS_GMM_MS_EV_DISABLE_GPRS_MODE:
gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_NULL);
break;
case GPRS_GMM_MS_EV_ATTACH_REQUESTED:
+ rc = gprs_gmm_tx_att_req(ctx->gmme,
+ ctx->attach.type,
+ ctx->attach.with_imsi);
+ if (rc < 0)
+ return;
gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED_INITIATED);
break;
default:
@@ -60,12 +75,36 @@
static void st_gmm_ms_registered_initiated(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
+ struct gprs_gmm_ms_fsm_ctx *ctx = (struct gprs_gmm_ms_fsm_ctx *)fi->priv;
+ int rc;
+
switch (event) {
+ case GPRS_GMM_MS_EV_ATTACH_REQUESTED:
+ /* Upper layers request us to retry attaching: */
+ rc = gprs_gmm_tx_att_req(ctx->gmme,
+ ctx->attach.type,
+ ctx->attach.with_imsi);
+ break;
case GPRS_GMM_MS_EV_ATTACH_REJECTED:
case GPRS_GMM_MS_EV_LOW_LVL_FAIL:
gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED);
break;
case GPRS_GMM_MS_EV_ATTACH_ACCEPTED:
+ if (ctx->attach.explicit_att) {
+ /* Submit GMMREG-ATTACH-CNF as per TS 24.007 Annex C.1 */
+ rc = gprs_gmm_submit_gmmreg_attach_cnf(ctx->gmme, true, 0);
+ if (rc < 0)
+ return;
+ }
+ if (ctx->attach.implicit_att) {
+ /* Submit GMMSM-ESTABLISH-CNF as per TS 24.007 Annex C.3 */
+ unsigned int i;
+ for (i = 0; i < ctx->attach.num_sess_id; i++) {
+ rc = gprs_gmm_submit_gmmsm_establish_cnf(ctx->gmme, ctx->attach.sess_id[i], true, 0);
+ if (rc < 0)
+ return;
+ }
+ }
gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED);
break;
case GPRS_GMM_MS_EV_DETACH_REQUESTED:
@@ -78,7 +117,6 @@
static void st_gmm_ms_registered(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
- struct gprs_gmm_ms_fsm_ctx *ctx = (struct gprs_gmm_ms_fsm_ctx *)fi->priv;
switch (event) {
case GPRS_GMM_MS_EV_SR_REQUESTED:
gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED);
@@ -87,7 +125,6 @@
gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_RAU_INITIATED);
break;
case GPRS_GMM_MS_EV_DETACH_REQUESTED:
- ctx->detach_type = *((enum osmo_gprs_gmm_detach_ms_type *)data);
gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED_INITIATED);
break;
default:
@@ -170,12 +207,14 @@
X(GPRS_GMM_MS_ST_REGISTERED_INITIATED)|
X(GPRS_GMM_MS_ST_DEREGISTERED),
.name = "Deregistered",
+ .onenter = st_gmm_ms_deregistered_on_enter,
.action = st_gmm_ms_deregistered,
},
[GPRS_GMM_MS_ST_REGISTERED_INITIATED] = {
.in_event_mask =
X(GPRS_GMM_MS_EV_ATTACH_REJECTED) |
X(GPRS_GMM_MS_EV_LOW_LVL_FAIL) |
+ X(GPRS_GMM_MS_EV_ATTACH_REQUESTED) |
X(GPRS_GMM_MS_EV_ATTACH_ACCEPTED) |
X(GPRS_GMM_MS_EV_DETACH_REQUESTED),
.out_state_mask =
@@ -294,3 +333,65 @@
{
osmo_fsm_inst_free(ctx->fi);
}
+
+int gprs_gmm_ms_fsm_ctx_request_attach(struct gprs_gmm_ms_fsm_ctx *ctx,
+ enum osmo_gprs_gmm_attach_type attach_type,
+ bool attach_with_imsi,
+ bool explicit_attach,
+ uint32_t sess_id)
+{
+ int rc;
+
+ ctx->attach.type = attach_type;
+ ctx->attach.with_imsi = attach_with_imsi;
+ if (explicit_attach)
+ ctx->attach.explicit_att = true;
+ else
+ ctx->attach.implicit_att = true;
+
+ if (!explicit_attach) {
+ unsigned int i;
+ bool found = false;
+ if (ctx->attach.num_sess_id == ARRAY_SIZE(ctx->attach.sess_id))
+ return -ENOMEM;
+ for (i = 0; i < ctx->attach.num_sess_id; i++) {
+ if (sess_id == ctx->attach.sess_id[i]) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ ctx->attach.sess_id[ctx->attach.num_sess_id] = sess_id;
+ ctx->attach.num_sess_id++;
+ }
+ }
+
+ rc = osmo_fsm_inst_dispatch(ctx->fi, GPRS_GMM_MS_EV_ATTACH_REQUESTED, NULL);
+ return rc;
+}
+
+int gprs_gmm_ms_fsm_ctx_request_detach(struct gprs_gmm_ms_fsm_ctx *ctx,
+ enum osmo_gprs_gmm_detach_ms_type detach_type,
+ enum osmo_gprs_gmm_detach_poweroff_type poweroff_type)
+{
+ int rc;
+
+ ctx->detach.type = detach_type;
+ ctx->detach.poweroff_type = poweroff_type;
+
+ switch (poweroff_type) {
+ case OSMO_GPRS_GMM_DETACH_POWEROFF_TYPE_NORMAL:
+ /* C.3 MS initiated DETACH, GPRS only */
+ rc = osmo_fsm_inst_dispatch(ctx->fi, GPRS_GMM_MS_EV_DETACH_REQUESTED, NULL);
+ break;
+ case OSMO_GPRS_GMM_DETACH_POWEROFF_TYPE_POWEROFF:
+ /* C.4 POWER-OFF DETACH, GPRS only */
+ rc = osmo_fsm_inst_dispatch(ctx->fi, GPRS_GMM_MS_EV_DETACH_REQUESTED_POWEROFF, NULL);
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+
+ rc = gprs_gmm_tx_detach_req(ctx->gmme, detach_type, poweroff_type);
+ return rc;
+}
diff --git a/src/gmm/gmm_prim.c b/src/gmm/gmm_prim.c
index c4de625..ce7afb2 100644
--- a/src/gmm/gmm_prim.c
+++ b/src/gmm/gmm_prim.c
@@ -271,45 +271,51 @@
}
/* 3GPP TS 24.007 9.5.1.1 GMMSM-ESTABLISH-REQ:*/
-struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmsm_establish_req(void)
+struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmsm_establish_req(uint32_t id)
{
struct osmo_gprs_gmm_prim *gmm_prim;
gmm_prim = gmm_prim_gmmsm_alloc(OSMO_GPRS_GMM_GMMSM_ESTABLISH, PRIM_OP_REQUEST, 0);
+ gmm_prim->gmmsm.sess_id = id;
return gmm_prim;
}
/* 3GPP TS 24.007 9.5.1.2 GMMSM-ESTABLISH-CNF:*/
-struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_establish_cnf(uint8_t cause)
+struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_establish_cnf(uint32_t id, uint8_t cause)
{
struct osmo_gprs_gmm_prim *gmm_prim;
gmm_prim = gmm_prim_gmmsm_alloc(OSMO_GPRS_GMM_GMMSM_ESTABLISH, PRIM_OP_CONFIRM, 0);
- gmm_prim->gmmsm.establish_cnf.cause = cause;
+ gmm_prim->gmmsm.sess_id = id;
+ gmm_prim->gmmsm.establish_cnf.accepted = (cause == 0);
+ gmm_prim->gmmsm.establish_cnf.rej.cause = cause;
return gmm_prim;
}
/* 3GPP TS 24.007 9.5.1.4 GMMSM-RELEASE-IND:*/
-struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_release_ind(void)
+struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_release_ind(uint32_t id)
{
struct osmo_gprs_gmm_prim *gmm_prim;
gmm_prim = gmm_prim_gmmsm_alloc(OSMO_GPRS_GMM_GMMSM_RELEASE, PRIM_OP_INDICATION, 0);
+ gmm_prim->gmmsm.sess_id = id;
return gmm_prim;
}
-/* 3GPP TS 24.007 9.5.1.5 GMMRSM-UNITDATA-REQ:*/
-struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmsm_unitdata_req(uint8_t *smpdu, unsigned int smpdu_len)
+/* 3GPP TS 24.007 9.5.1.5 GMMSM-UNITDATA-REQ:*/
+struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmsm_unitdata_req(uint32_t id, uint8_t *smpdu, unsigned int smpdu_len)
{
struct osmo_gprs_gmm_prim *gmm_prim;
gmm_prim = gmm_prim_gmmsm_alloc(OSMO_GPRS_GMM_GMMSM_UNITDATA, PRIM_OP_REQUEST, smpdu_len);
+ gmm_prim->gmmsm.sess_id = id;
gmm_prim->gmmsm.unitdata_req.smpdu = smpdu;
gmm_prim->gmmsm.unitdata_req.smpdu_len = smpdu_len;
return gmm_prim;
}
-/* 3GPP TS 24.007 9.5.1.6 GMMRSM-UNITDATA-IND:*/
-struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_unitdata_ind(uint8_t *smpdu, unsigned int smpdu_len)
+/* 3GPP TS 24.007 9.5.1.6 GMMSM-UNITDATA-IND:*/
+struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmsm_unitdata_ind(uint32_t id, uint8_t *smpdu, unsigned int smpdu_len)
{
struct osmo_gprs_gmm_prim *gmm_prim;
gmm_prim = gmm_prim_gmmsm_alloc(OSMO_GPRS_GMM_GMMSM_UNITDATA, PRIM_OP_INDICATION, smpdu_len);
+ gmm_prim->gmmsm.sess_id = id;
gmm_prim->gmmsm.unitdata_ind.smpdu = smpdu;
gmm_prim->gmmsm.unitdata_ind.smpdu_len = smpdu_len;
return gmm_prim;
@@ -363,15 +369,10 @@
if (gmm_prim->gmmreg.attach_req.imeisv[0] != '\0')
OSMO_STRLCPY_ARRAY(gmme->imeisv, gmm_prim->gmmreg.attach_req.imeisv);
- rc = gprs_gmm_tx_att_req(gmme,
- gmm_prim->gmmreg.attach_req.attach_type,
- gmm_prim->gmmreg.attach_req.attach_with_imsi);
-
- if (rc < 0)
- return rc;
-
- rc = osmo_fsm_inst_dispatch(gmme->ms_fsm.fi, GPRS_GMM_MS_EV_ATTACH_REQUESTED, NULL);
-
+ rc = gprs_gmm_ms_fsm_ctx_request_attach(&gmme->ms_fsm,
+ gmm_prim->gmmreg.attach_req.attach_type,
+ gmm_prim->gmmreg.attach_req.attach_with_imsi,
+ true, 0);
return rc;
}
@@ -387,23 +388,9 @@
return -EINVAL;
}
- switch (gmm_prim->gmmreg.detach_req.poweroff_type) {
- case OSMO_GPRS_GMM_DETACH_POWEROFF_TYPE_NORMAL:
- /* C.3 MS initiated DETACH, GPRS only */
- rc = osmo_fsm_inst_dispatch(gmme->ms_fsm.fi, GPRS_GMM_MS_EV_DETACH_REQUESTED,
- &gmm_prim->gmmreg.detach_req.detach_type);
- break;
- case OSMO_GPRS_GMM_DETACH_POWEROFF_TYPE_POWEROFF:
- /* C.4 POWER-OFF DETACH, GPRS only */
- rc = osmo_fsm_inst_dispatch(gmme->ms_fsm.fi, GPRS_GMM_MS_EV_DETACH_REQUESTED_POWEROFF, NULL);
- break;
- default:
- OSMO_ASSERT(0);
- }
-
- rc = gprs_gmm_tx_detach_req(gmme,
- gmm_prim->gmmreg.detach_req.detach_type,
- gmm_prim->gmmreg.detach_req.poweroff_type);
+ rc = gprs_gmm_ms_fsm_ctx_request_detach(&gmme->ms_fsm,
+ gmm_prim->gmmreg.detach_req.detach_type,
+ gmm_prim->gmmreg.detach_req.poweroff_type);
return rc;
}
@@ -428,9 +415,26 @@
static int gprs_gmm_prim_handle_gmmsm_establish_req(struct osmo_gprs_gmm_prim *gmm_prim)
{
int rc;
+ struct gprs_gmm_entity *gmme;
- rc = gprs_gmm_prim_handle_unsupported(gmm_prim);
+ gmme = llist_first_entry_or_null(&g_ctx->gmme_list, struct gprs_gmm_entity, list);
+ if (!gmme) {
+ gmme = gprs_gmm_gmme_alloc();
+ OSMO_ASSERT(gmme);
+ }
+ gmme->ptmsi = gmm_prim->gmmsm.establish_req.ptmsi;
+ if (gmm_prim->gmmsm.establish_req.imsi[0] != '\0')
+ OSMO_STRLCPY_ARRAY(gmme->imsi, gmm_prim->gmmsm.establish_req.imsi);
+ if (gmm_prim->gmmsm.establish_req.imei[0] != '\0')
+ OSMO_STRLCPY_ARRAY(gmme->imei, gmm_prim->gmmsm.establish_req.imei);
+ if (gmm_prim->gmmsm.establish_req.imeisv[0] != '\0')
+ OSMO_STRLCPY_ARRAY(gmme->imeisv, gmm_prim->gmmsm.establish_req.imeisv);
+ rc = gprs_gmm_ms_fsm_ctx_request_attach(&gmme->ms_fsm,
+ gmm_prim->gmmsm.establish_req.attach_type,
+ gmm_prim->gmmsm.establish_req.attach_with_imsi,
+ false,
+ gmm_prim->gmmsm.sess_id);
return rc;
}
diff --git a/src/sm/Makefile.am b/src/sm/Makefile.am
new file mode 100644
index 0000000..8fb9090
--- /dev/null
+++ b/src/sm/Makefile.am
@@ -0,0 +1,40 @@
+# 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-sm.la \
+ $(NULL)
+
+libosmo_gprs_sm_la_SOURCES = \
+ sm.c \
+ sm_ms_fsm.c \
+ sm_pdu.c \
+ sm_prim.c \
+ misc.c \
+ $(NULL)
+
+libosmo_gprs_sm_la_LDFLAGS = \
+ -export-symbols-regex '^osmo_' \
+ -version-info $(LIBVERSION) \
+ -no-undefined \
+ $(NULL)
+
+libosmo_gprs_sm_la_LIBADD = \
+ $(top_builddir)/src/gmm/libosmo-gprs-gmm.la \
+ $(LIBOSMOCORE_LIBS) \
+ $(LIBOSMOGSM_LIBS) \
+ -lm \
+ $(NULL)
diff --git a/src/sm/misc.c b/src/sm/misc.c
new file mode 100644
index 0000000..10cb0dd
--- /dev/null
+++ b/src/sm/misc.c
@@ -0,0 +1,34 @@
+/*
+ * (C) 2023 by sysmocom - s.f.m.c. GmbH <info(a)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/sm/sm.h>
+#include <osmocom/gprs/sm/sm_ms_fsm.h>
+
+int g_sm_log_cat[_OSMO_GPRS_SM_LOGC_MAX] = { [0 ... _OSMO_GPRS_SM_LOGC_MAX - 1] = DLGLOBAL };
+
+void osmo_gprs_sm_set_log_cat(enum osmo_gprs_sm_log_cat logc, int logc_num)
+{
+ OSMO_ASSERT(logc < _OSMO_GPRS_SM_LOGC_MAX);
+ g_sm_log_cat[logc] = logc_num;
+
+ gprs_sm_ms_fsm_set_log_cat(logc_num);
+}
diff --git a/src/sm/sm.c b/src/sm/sm.c
new file mode 100644
index 0000000..59a5e7b
--- /dev/null
+++ b/src/sm/sm.c
@@ -0,0 +1,304 @@
+/* GPRS SM as per 3GPP TS 24.008, TS 24.007 */
+/*
+ * (C) 2023 by sysmocom - s.f.m.c. GmbH <info(a)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/core/tdef.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
+
+#include <osmocom/gprs/sm/sm.h>
+#include <osmocom/gprs/sm/sm_prim.h>
+#include <osmocom/gprs/sm/sm_private.h>
+#include <osmocom/gprs/sm/sm_ms_fsm.h>
+#include <osmocom/gprs/sm/sm_pdu.h>
+
+struct gprs_sm_ctx *g_ctx;
+
+/* TS 24.008 */
+static struct osmo_tdef T_defs_sm[] = {
+ { .T=3380, .default_val=30, .desc = "" },
+ { 0 } /* empty item at the end */
+};
+
+static void gprs_sm_ctx_free(void)
+{
+ struct gprs_sm_ms *ms;
+
+ while ((ms = llist_first_entry_or_null(&g_ctx->ms_list, struct gprs_sm_ms, list)))
+ gprs_sm_ms_free(ms);
+
+ talloc_free(g_ctx);
+}
+
+int osmo_gprs_sm_init(enum osmo_gprs_sm_location location)
+{
+ bool first_init = true;
+ int rc;
+ OSMO_ASSERT(location == OSMO_GPRS_SM_LOCATION_MS || location == OSMO_GPRS_SM_LOCATION_NETWORK)
+
+ if (g_ctx) {
+ first_init = false;
+ gprs_sm_ctx_free();
+ }
+
+ g_ctx = talloc_zero(NULL, struct gprs_sm_ctx);
+ g_ctx->location = location;
+ g_ctx->T_defs = T_defs_sm;
+ INIT_LLIST_HEAD(&g_ctx->ms_list);
+
+ osmo_tdefs_reset(g_ctx->T_defs);
+
+ if (first_init) {
+ rc = gprs_sm_ms_fsm_init();
+ if (rc != 0) {
+ TALLOC_FREE(g_ctx);
+ return rc;
+ }
+ }
+ return 0;
+}
+
+struct gprs_sm_ms *gprs_sm_ms_alloc(uint32_t ms_id)
+{
+ struct gprs_sm_ms *ms;
+
+ ms = talloc_zero(g_ctx, struct gprs_sm_ms);
+ if (!ms)
+ return NULL;
+
+ ms->ms_id = ms_id;
+
+ llist_add(&ms->list, &g_ctx->ms_list);
+
+ return ms;
+}
+
+void gprs_sm_ms_free(struct gprs_sm_ms *ms)
+{
+ unsigned int i;
+ if (!ms)
+ return;
+
+ LOGMS(ms, LOGL_DEBUG, "free()\n");
+
+ for (i = 0; i < ARRAY_SIZE(ms->pdp); i++)
+ gprs_sm_entity_free(ms->pdp[i]);
+
+ llist_del(&ms->list);
+ talloc_free(ms);
+}
+
+struct gprs_sm_ms *gprs_sm_find_ms_by_id(uint32_t ms_id)
+{
+ struct gprs_sm_ms *ms;
+
+ llist_for_each_entry(ms, &g_ctx->ms_list, list) {
+ if (ms->ms_id == ms_id)
+ return ms;
+ }
+ return NULL;
+}
+
+struct gprs_sm_entity *gprs_sm_entity_alloc(struct gprs_sm_ms *ms, uint32_t nsapi)
+{
+ struct gprs_sm_entity *sme;
+ sme = talloc_zero(g_ctx, struct gprs_sm_entity);
+ if (!sme)
+ return NULL;
+
+ sme->ms = ms;
+ sme->sess_id = g_ctx->next_sess_id++;
+ sme->nsapi = nsapi;
+
+ if (gprs_sm_ms_fsm_ctx_init(&sme->ms_fsm, sme) < 0) {
+ talloc_free(sme);
+ return NULL;
+ }
+
+ OSMO_ASSERT(sme->ms->pdp[sme->nsapi] == NULL);
+ sme->ms->pdp[sme->nsapi] = sme;
+ return sme;
+}
+
+void gprs_sm_entity_free(struct gprs_sm_entity *sme)
+{
+ if (!sme)
+ return;
+
+ gprs_sm_ms_fsm_ctx_release(&sme->ms_fsm);
+
+ sme->ms->pdp[sme->nsapi] = NULL;
+ talloc_free(sme);
+}
+
+struct gprs_sm_entity *gprs_sm_find_sme_by_sess_id(uint32_t sess_id)
+{
+ struct gprs_sm_ms *ms;
+ unsigned int i;
+
+ llist_for_each_entry(ms, &g_ctx->ms_list, list) {
+ for (i = 0; i < ARRAY_SIZE(ms->pdp); i++) {
+ if (!ms->pdp[i])
+ continue;
+ if (ms->pdp[i]->sess_id != sess_id)
+ continue;
+ return ms->pdp[i];
+ }
+ }
+ return NULL;
+}
+
+int gprs_sm_submit_gmmsm_assign_req(const struct gprs_sm_entity *sme)
+{
+ struct gprs_sm_ms *ms = sme->ms;
+ struct osmo_gprs_gmm_prim *gmm_prim_tx;
+ int rc;
+
+ gmm_prim_tx = osmo_gprs_gmm_prim_alloc_gmmsm_establish_req(sme->sess_id);
+ gmm_prim_tx->gmmsm.establish_req.attach_type = OSMO_GPRS_GMM_ATTACH_TYPE_GPRS;
+ gmm_prim_tx->gmmsm.establish_req.ptmsi = ms->gmm.ptmsi;
+ OSMO_STRLCPY_ARRAY(gmm_prim_tx->gmmsm.establish_req.imsi, ms->gmm.imsi);
+ OSMO_STRLCPY_ARRAY(gmm_prim_tx->gmmsm.establish_req.imei, ms->gmm.imei);
+ OSMO_STRLCPY_ARRAY(gmm_prim_tx->gmmsm.establish_req.imeisv, ms->gmm.imeisv);
+
+ rc = gprs_sm_prim_call_gmm_down_cb(gmm_prim_tx);
+ return rc;
+}
+
+int gprs_sm_submit_smreg_pdp_act_cnf(const struct gprs_sm_entity *sme, enum gsm48_gsm_cause cause)
+{
+ struct osmo_gprs_sm_prim *sm_prim_tx;
+ int rc;
+
+ sm_prim_tx = gprs_sm_prim_alloc_smreg_pdp_act_cnf();
+ sm_prim_tx->smreg.ms_id = sme->ms->ms_id;
+ sm_prim_tx->smreg.pdp_act_cnf.accepted = (cause != 0);
+ sm_prim_tx->smreg.pdp_act_cnf.nsapi = sme->nsapi;
+ if (!sm_prim_tx->smreg.pdp_act_cnf.accepted)
+ sm_prim_tx->smreg.pdp_act_cnf.rej.cause = cause;
+
+ rc = gprs_sm_prim_call_up_cb(sm_prim_tx);
+ return rc;
+}
+
+/* Tx SM Activate PDP context request, 9.5.1 */
+int gprs_sm_tx_act_pdp_ctx_req(struct gprs_sm_entity *sme)
+{
+ struct osmo_gprs_gmm_prim *gmm_prim;
+ int rc;
+ struct msgb *msg;
+
+ LOGSME(sme, LOGL_INFO, "Tx SM Activate PDP Context Request\n");
+ gmm_prim = osmo_gprs_gmm_prim_alloc_gmmsm_unitdata_req(
+ sme->ms->ms_id, NULL, GPRS_SM_ALLOC_SIZE);
+ msg = gmm_prim->oph.msg;
+ msg->l3h = msg->tail;
+ rc = gprs_sm_build_act_pdp_ctx_req(sme, msg);
+ if (rc < 0) {
+ msgb_free(msg);
+ return -EBADMSG;
+ }
+ gmm_prim->gmmsm.unitdata_req.smpdu = msg->l3h;
+ gmm_prim->gmmsm.unitdata_req.smpdu_len = msgb_l3len(msg);
+
+ rc = gprs_sm_prim_call_gmm_down_cb(gmm_prim);
+
+ return rc;
+}
+
+/* 3GPP TS 24.008 § 9.5.2: Activate PDP Context Accept */
+static int gprs_sm_rx_act_pdp_ack(struct gprs_sm_entity *sme,
+ struct gsm48_hdr *gh,
+ unsigned int len)
+{
+ struct tlv_parsed tp;
+ int rc;
+ uint8_t radio_prio, llc_sapi;
+ uint8_t *ofs = (uint8_t *)gh;
+ uint8_t qos_len;
+ uint8_t *qos;
+
+ ofs += sizeof(*gh);
+ //uint8_t transaction_id = gsm48_hdr_trans_id(gh);
+
+ LOGSME(sme, LOGL_INFO, "Rx SM Activate PDP Context Accept\n");
+
+ if (len < (ofs + 2) - (uint8_t *)gh)
+ goto tooshort;
+ llc_sapi = *ofs++;
+ qos_len = *ofs++;
+
+ if (len < (ofs + qos_len) - (uint8_t *)gh)
+ goto tooshort;
+ qos = ofs;
+ ofs += qos_len;
+
+ if (len < (ofs + 1) - (uint8_t *)gh)
+ goto tooshort;
+
+ radio_prio = *ofs++;
+
+ rc = gprs_sm_tlv_parse(&tp, ofs, len - (ofs - (uint8_t *)gh));
+ if (rc < 0) {
+ LOGSME(sme, LOGL_ERROR, "Rx SM Activate PDP Context Accept: failed to parse TLVs %d\n", rc);
+ goto rejected;
+ }
+
+ (void)llc_sapi;
+ (void)qos;
+ (void)radio_prio;
+
+ rc = osmo_fsm_inst_dispatch(sme->ms_fsm.fi, GPRS_SM_MS_EV_RX_ACT_PDP_CTX_ACC, NULL);
+ if (rc < 0)
+ goto rejected;
+ return rc;
+
+tooshort:
+ LOGSME(sme, LOGL_ERROR, "Rx GMM message too short! len=%u\n", len);
+rejected:
+ return -EINVAL; /* TODO: what to do on error? */
+}
+
+/* Rx Session Management PDU */
+int gprs_sm_rx(struct gprs_sm_entity *sme, struct gsm48_hdr *gh, unsigned int len)
+{
+ int rc = 0;
+ if (len < sizeof(struct gsm48_hdr)) {
+ LOGSME(sme, LOGL_ERROR, "Rx GMM message too short! len=%u\n", len);
+ return -EINVAL;
+ }
+
+ switch (gh->msg_type) {
+ case GSM48_MT_GSM_ACT_PDP_ACK:
+ rc = gprs_sm_rx_act_pdp_ack(sme, gh, len);
+ break;
+ default:
+ LOGSME(sme, LOGL_ERROR,
+ "Rx SM message not implemented! type=%u len=%u\n",
+ gh->msg_type, len);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
diff --git a/src/sm/sm_ms_fsm.c b/src/sm/sm_ms_fsm.c
new file mode 100644
index 0000000..b6fb79f
--- /dev/null
+++ b/src/sm/sm_ms_fsm.c
@@ -0,0 +1,270 @@
+/* SM states in the MS, 3GPP TS 24.008 § 6.1.2.1 */
+/*
+ * (C) 2023 by sysmocom - s.m.f.c. GmbH <info(a)sysmocom.de>
+ * All Rights Reserved
+ *
+ * SPDX-License-Identifier: AGPL-3.0+
+ *
+ * Author: Pau Espin Pedrol <pespin(a)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/licenses/>.
+ */
+#include <errno.h>
+#include <osmocom/core/tdef.h>
+#include <osmocom/core/utils.h>
+
+#include <osmocom/gprs/sm/sm_ms_fsm.h>
+#include <osmocom/gprs/sm/sm.h>
+#include <osmocom/gprs/sm/sm_private.h>
+
+#define X(s) (1 << (s))
+
+static const struct osmo_tdef_state_timeout sm_ms_fsm_timeouts[32] = {
+ [GPRS_SM_MS_ST_PDP_INACTIVE] = {},
+ [GPRS_SM_MS_ST_PDP_ACTIVE_PENDING] = { .T = 3380 },
+ [GPRS_SM_MS_ST_PDP_ACTIVE] = {},
+ [GPRS_SM_MS_ST_PDP_MODIFY_PENDING] = {},
+ [GPRS_SM_MS_ST_PDP_INACTIVE_PENDING] = {},
+};
+
+#define sm_ms_fsm_state_chg(fi, NEXT_STATE) \
+ osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, sm_ms_fsm_timeouts, g_ctx->T_defs, -1)
+
+static void st_sm_ms_pdp_inactive(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch (event) {
+ case GPRS_SM_MS_EV_TX_ACT_PDP_CTX_REQ:
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_ACTIVE_PENDING);
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static void st_sm_ms_pdp_active_pending_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gprs_sm_ms_fsm_ctx *ctx = (struct gprs_sm_ms_fsm_ctx *)fi->priv;
+
+ gprs_sm_submit_gmmsm_assign_req(ctx->sme);
+}
+
+static void st_sm_ms_pdp_active_pending(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct gprs_sm_ms_fsm_ctx *ctx = (struct gprs_sm_ms_fsm_ctx *)fi->priv;
+
+ switch (event) {
+ case GPRS_SM_MS_EV_RX_GMM_ESTABLISH_CNF:
+ gprs_sm_tx_act_pdp_ctx_req(ctx->sme);
+ break;
+ case GPRS_SM_MS_EV_RX_GMM_ESTABLISH_REJ:
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_INACTIVE);
+ break;
+ case GPRS_SM_MS_EV_RX_ACT_PDP_CTX_REJ:
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_INACTIVE);
+ gprs_sm_submit_smreg_pdp_act_cnf(ctx->sme, *((enum gsm48_gsm_cause *)data));
+ break;
+ case GPRS_SM_MS_EV_RX_ACT_PDP_CTX_ACC:
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_ACTIVE);
+ gprs_sm_submit_smreg_pdp_act_cnf(ctx->sme, (enum gsm48_gsm_cause)0);
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static void st_sm_ms_pdp_active(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch (event) {
+ case GPRS_SM_MS_EV_RX_DEACT_PDP_CTX_REQ:
+ /* TODO: Tx PDP DEACT ACC */
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_INACTIVE);
+ break;
+ case GPRS_SM_MS_EV_TX_DEACT_PDP_CTX_REQ:
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_INACTIVE_PENDING);
+ break;
+ case GPRS_SM_MS_EV_TX_MOD_PDP_CTX_REQ:
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_MODIFY_PENDING);
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static void st_sm_ms_pdp_modify_pending(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch (event) {
+ case GPRS_SM_MS_EV_RX_DEACT_PDP_CTX_REQ:
+ /* TODO: Tx PDP DEACT ACC */
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_INACTIVE);
+ break;
+ case GPRS_SM_MS_EV_RX_MOD_PDP_CTX_REJ:
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_INACTIVE_PENDING);
+ break;
+ case GPRS_SM_MS_EV_RX_MOD_PDP_CTX_ACC:
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_ACTIVE);
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static void st_sm_ms_pdp_inactive_pending(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch (event) {
+ case GPRS_SM_MS_EV_RX_DEACT_PDP_CTX_ACC:
+ sm_ms_fsm_state_chg(fi, GPRS_SM_MS_ST_PDP_INACTIVE);
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static int sm_ms_fsm_timer_cb(struct osmo_fsm_inst *fi)
+{
+ struct gprs_sm_ms_fsm_ctx *ctx = (struct gprs_sm_ms_fsm_ctx *)fi->priv;
+
+ switch (fi->T) {
+ case 3380:
+ ctx->act_pdp_ctx_attempts++;
+ LOGPFSML(ctx->fi, LOGL_INFO, "T3380 timeout attempts=%u\n", ctx->act_pdp_ctx_attempts);
+ OSMO_ASSERT(fi->state == GPRS_SM_MS_ST_PDP_ACTIVE_PENDING);
+ if (ctx->act_pdp_ctx_attempts == 4) {
+ enum gsm48_gsm_cause cause = GSM_CAUSE_SERV_OPT_TEMP_OOO;
+ /* TS 24.008 6.1.3.1.5:
+ * "On the first expiry of the timer T3380, the MS shall resend the ACTIVATE PDP
+ * CONTEXT REQUEST and shall reset and restart timer T3380. This retransmission is
+ * repeated four times, i.e. on the fifth expiry of timer T3380, the MS shall release
+ * all resources possibly allocated for this invocation and shall abort the procedure"
+ */
+ LOGPFSML(ctx->fi, LOGL_NOTICE, "TBF establishment failure (T3380 timeout attempts=%u)\n",
+ ctx->act_pdp_ctx_attempts);
+
+ osmo_fsm_inst_dispatch(ctx->fi, GPRS_SM_MS_EV_RX_ACT_PDP_CTX_REJ, &cause);
+ return 0;
+ }
+ /* reinit tx of Act Pdp Ctx Req and rearm timer by re-entering state: */
+ sm_ms_fsm_state_chg(ctx->fi, GPRS_SM_MS_ST_PDP_ACTIVE_PENDING);
+ break;
+ default:
+ OSMO_ASSERT(0);
+ }
+ return 0;
+}
+
+static struct osmo_fsm_state sm_ms_fsm_states[] = {
+ [GPRS_SM_MS_ST_PDP_INACTIVE] = {
+ .in_event_mask =
+ X(GPRS_SM_MS_EV_TX_ACT_PDP_CTX_REQ),
+ .out_state_mask =
+ X(GPRS_SM_MS_ST_PDP_ACTIVE_PENDING),
+ .name = "INACTIVE",
+ .action = st_sm_ms_pdp_inactive,
+ },
+ [GPRS_SM_MS_ST_PDP_ACTIVE_PENDING] = {
+ .in_event_mask =
+ X(GPRS_SM_MS_EV_RX_GMM_ESTABLISH_CNF) |
+ X(GPRS_SM_MS_EV_RX_GMM_ESTABLISH_REJ) |
+ X(GPRS_SM_MS_EV_RX_ACT_PDP_CTX_REJ) |
+ X(GPRS_SM_MS_EV_RX_ACT_PDP_CTX_ACC),
+ .out_state_mask =
+ X(GPRS_SM_MS_ST_PDP_INACTIVE) |
+ X(GPRS_SM_MS_ST_PDP_ACTIVE_PENDING) |
+ X(GPRS_SM_MS_ST_PDP_ACTIVE),
+ .name = "PDP_ACTIVE_PENDING",
+ .onenter = st_sm_ms_pdp_active_pending_on_enter,
+ .action = st_sm_ms_pdp_active_pending,
+ },
+ [GPRS_SM_MS_ST_PDP_ACTIVE] = {
+ .in_event_mask =
+ X(GPRS_SM_MS_EV_RX_DEACT_PDP_CTX_REQ) |
+ X(GPRS_SM_MS_EV_TX_DEACT_PDP_CTX_REQ)|
+ X(GPRS_SM_MS_EV_TX_MOD_PDP_CTX_REQ),
+ .out_state_mask =
+ X(GPRS_SM_MS_ST_PDP_INACTIVE) |
+ X(GPRS_SM_MS_ST_PDP_INACTIVE_PENDING) |
+ X(GPRS_SM_MS_ST_PDP_MODIFY_PENDING),
+ .name = "PDP_ACTIVE",
+ .action = st_sm_ms_pdp_active,
+ },
+ [GPRS_SM_MS_ST_PDP_MODIFY_PENDING] = {
+ .in_event_mask =
+ X(GPRS_SM_MS_EV_RX_DEACT_PDP_CTX_REQ) |
+ X(GPRS_SM_MS_EV_RX_MOD_PDP_CTX_REJ) |
+ X(GPRS_SM_MS_EV_RX_MOD_PDP_CTX_ACC),
+ .out_state_mask =
+ X(GPRS_SM_MS_ST_PDP_INACTIVE) |
+ X(GPRS_SM_MS_ST_PDP_ACTIVE) |
+ X(GPRS_SM_MS_ST_PDP_INACTIVE_PENDING),
+ .name = "PDP_MODIFY_PENDING",
+ .action = st_sm_ms_pdp_modify_pending,
+ },
+ [GPRS_SM_MS_ST_PDP_INACTIVE_PENDING] = {
+ .in_event_mask =
+ X(GPRS_SM_MS_EV_RX_DEACT_PDP_CTX_ACC),
+ .out_state_mask =
+ X(GPRS_SM_MS_ST_PDP_INACTIVE),
+ .name = "PDP_INACTIVE_PENDING",
+ .action = st_sm_ms_pdp_inactive_pending,
+ },
+};
+
+const struct value_string sm_ms_fsm_event_names[] = {
+ { GPRS_SM_MS_EV_RX_GMM_ESTABLISH_CNF, "RX GMM_ESTABLISH_CNF" },
+ { GPRS_SM_MS_EV_RX_GMM_ESTABLISH_REJ, "RX GMM_ESTABLISH_REJ" },
+ { GPRS_SM_MS_EV_TX_ACT_PDP_CTX_REQ, "TX_ACT_PDP_CTX_REQ" },
+ { GPRS_SM_MS_EV_RX_ACT_PDP_CTX_REJ, "RX_ACT_PDP_CTX_REJ" },
+ { GPRS_SM_MS_EV_RX_ACT_PDP_CTX_ACC, "RX_ACT_PDP_CTX_ACC" },
+ { GPRS_SM_MS_EV_TX_DEACT_PDP_CTX_REQ, "TX_DEACT_PDP_CTX_REQ" },
+ { GPRS_SM_MS_EV_RX_DEACT_PDP_CTX_REQ, "RX_DEACT_PDP_CTX_REQ" },
+ { GPRS_SM_MS_EV_RX_DEACT_PDP_CTX_ACC, "RX_DEACT_PDP_CTX_ACC" },
+ { GPRS_SM_MS_EV_TX_MOD_PDP_CTX_REQ, "TX_MOD_PDP_CTX_REQ" },
+ { GPRS_SM_MS_EV_RX_MOD_PDP_CTX_REJ, "RX_MOD_PDP_CTX_REJ" },
+ { GPRS_SM_MS_EV_RX_MOD_PDP_CTX_ACC, "RX_MOD_PDP_CTX_ACC" },
+ { 0, NULL }
+};
+
+struct osmo_fsm sm_ms_fsm = {
+ .name = "SM_MS",
+ .states = sm_ms_fsm_states,
+ .num_states = ARRAY_SIZE(sm_ms_fsm_states),
+ .timer_cb = sm_ms_fsm_timer_cb,
+ .event_names = sm_ms_fsm_event_names,
+ .log_subsys = DLGLOBAL, /* updated dynamically through gprs_sm_ms_fsm_set_log_cat() */
+ .timer_cb = sm_ms_fsm_timer_cb,
+};
+
+int gprs_sm_ms_fsm_init(void)
+{
+ return osmo_fsm_register(&sm_ms_fsm);
+}
+
+void gprs_sm_ms_fsm_set_log_cat(int logcat)
+{
+ sm_ms_fsm.log_subsys = logcat;
+}
+
+int gprs_sm_ms_fsm_ctx_init(struct gprs_sm_ms_fsm_ctx *ctx, struct gprs_sm_entity *sme)
+{
+ ctx->sme = sme;
+ ctx->fi = osmo_fsm_inst_alloc(&sm_ms_fsm, sme, ctx, LOGL_INFO, NULL);
+ if (!ctx->fi)
+ return -ENODATA;
+
+ return 0;
+}
+
+void gprs_sm_ms_fsm_ctx_release(struct gprs_sm_ms_fsm_ctx *ctx)
+{
+ osmo_fsm_inst_free(ctx->fi);
+}
diff --git a/src/sm/sm_pdu.c b/src/sm/sm_pdu.c
new file mode 100644
index 0000000..3498a9c
--- /dev/null
+++ b/src/sm/sm_pdu.c
@@ -0,0 +1,131 @@
+/* SM PDUs, 3GPP TS 9.5 24.008 Session Management Messages */
+/* (C) 2023 by Sysmocom s.f.m.c. GmbH
+ *
+ * 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/bitvec.h>
+#include <osmocom/core/endian.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/protocol/gsm_04_08_gprs.h>
+#include <osmocom/gsm/apn.h>
+
+#include <osmocom/gprs/sm/sm_private.h>
+#include <osmocom/gprs/sm/sm_pdu.h>
+
+
+const struct tlv_definition gprs_sm_att_tlvdef = {
+ .def = {
+ [GSM48_IE_GSM_RADIO_PRIO] = {TLV_TYPE_SINGLE_TV, 1 },
+ [GSM48_IE_GSM_APN] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_PROTO_CONF_OPT] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_PDP_ADDR] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_AA_TMR] = { TLV_TYPE_TV, 1 },
+ [GSM48_IE_GSM_QOS] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_TFT] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_LLC_SAPI] = { TLV_TYPE_TV, 1 },
+ [GSM48_IE_GSM_PFI] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_NAME_FULL] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_NAME_SHORT] = { TLV_TYPE_TLV, 0 },
+ [GSM48_IE_GSM_TIMEZONE] = { TLV_TYPE_FIXED, 1 },
+ [GSM48_IE_GSM_UTC_AND_TZ] = { TLV_TYPE_FIXED, 7 },
+ [GSM48_IE_GSM_LSA_ID] = { TLV_TYPE_TLV, 0 },
+ },
+};
+
+/* 10.5.6.4 Packet data protocol address */
+static uint8_t gprs_sm_pdp_addr_enc_ietf(struct gprs_sm_pdp_addr *out,
+ enum osmo_gprs_sm_pdp_addr_ietf_type pdp_addr_ietf_type,
+ const struct osmo_sockaddr *pdp_addr_v4,
+ const struct osmo_sockaddr *pdp_addr_v6)
+{
+ memset(out, 0, sizeof(*out));
+
+ out->spare = 0x00;
+ out->organization = GPRS_SM_PDP_ADDR_ORG_IETF;
+ out->type = pdp_addr_ietf_type;
+
+ switch (pdp_addr_ietf_type) {
+ case OSMO_GPRS_SM_PDP_ADDR_IETF_IPV6:
+ memcpy(out->addr6, pdp_addr_v6->u.sin6.sin6_addr.s6_addr, sizeof(out->addr6));
+ return 2 + sizeof(out->addr6);
+ case OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4V6:
+ out->both.addr = pdp_addr_v4->u.sin.sin_addr.s_addr;
+ memcpy(out->both.addr6, pdp_addr_v6->u.sin6.sin6_addr.s6_addr, sizeof(out->both.addr6));
+ return 2 + sizeof(out->both.addr) + sizeof(out->both.addr6);
+ case OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4:
+ default:
+ /* All other values shall be interpreted as IPv4 address in this version of the protocol */
+ out->addr = pdp_addr_v4->u.sin.sin_addr.s_addr;
+ return 2 + sizeof(out->both.addr);
+ }
+}
+
+/* Chapter 9.4.1: Attach request */
+int gprs_sm_build_act_pdp_ctx_req(struct gprs_sm_entity *sme,
+ struct msgb *msg)
+{
+
+ struct gsm48_hdr *gh;
+ uint8_t *l;
+ int rc;
+ uint8_t transaction_id = sme->ti ^ 0x8; /* flip */
+
+ gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
+ gh->proto_discr = GSM48_PDISC_SM_GPRS | (transaction_id << 4);
+ gh->msg_type = GSM48_MT_GSM_ACT_PDP_REQ;
+
+ /* 10.5.6.2 Requested NSAPI */
+ msgb_v_put(msg, sme->nsapi);
+
+ /* 10.5.6.9 Requested LLC SAPI */
+ msgb_v_put(msg, sme->llc_sapi);
+
+ /* 10.5.6.5 Requested QoS */
+ msgb_lv_put(msg, sme->qos_len, (uint8_t *)&sme->qos);
+
+ /* 10.5.6.4 Requested PDP address */
+ l = msgb_put(msg, 1); /* len */
+ *l = gprs_sm_pdp_addr_enc_ietf((struct gprs_sm_pdp_addr *)msg->tail,
+ sme->pdp_addr_ietf_type,
+ &sme->pdp_addr_v4,
+ &sme->pdp_addr_v6);
+ msgb_put(msg, *l);
+
+ /* 10.5.6.1 Access point name (Optional) */
+ if (sme->apn[0] != '\0') {
+ msgb_v_put(msg, GSM48_IE_GSM_APN);
+ l = msgb_put(msg, 1); /* len */
+ rc = osmo_apn_from_str(msg->tail, msgb_tailroom(msg), sme->apn);
+ if (rc < 0)
+ return -EINVAL;
+ *l = rc;
+ }
+
+ /* 10.5.6.3 Protocol configuration options (Optional) */
+ if (sme->pco_len > 0)
+ msgb_tlv_put(msg, GSM48_IE_GSM_PROTO_CONF_OPT,
+ sme->pco_len, sme->pco);
+
+ /* TODO: other optional fields */
+ return 0;
+}
diff --git a/src/sm/sm_prim.c b/src/sm/sm_prim.c
new file mode 100644
index 0000000..197c8a4
--- /dev/null
+++ b/src/sm/sm_prim.c
@@ -0,0 +1,437 @@
+/* SM service primitive implementation as per 3GPP TS 44.065 */
+/*
+ * (C) 2023 by sysmocom - s.f.m.c. GmbH <info(a)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/sm/sm.h>
+#include <osmocom/gprs/sm/sm_prim.h>
+#include <osmocom/gprs/sm/sm_private.h>
+#include <osmocom/gprs/gmm/gmm_prim.h>
+
+#define SM_MSGB_HEADROOM 0
+
+const struct value_string osmo_gprs_sm_prim_sap_names[] = {
+ { OSMO_GPRS_SM_SAP_SMREG, "SMREG" },
+ { 0, NULL }
+};
+
+const struct value_string osmo_gprs_sm_smreg_prim_type_names[] = {
+ { OSMO_GPRS_SM_SMREG_PDP_ACTIVATE, "PDP_ACTIVATE" },
+ { OSMO_GPRS_SM_SMREG_PDP_DEACTIVATE, "PDP_DEACTIVATE" },
+ { OSMO_GPRS_SM_SMREG_PDP_MODIFY, "PDP_MODIFY"},
+ { OSMO_GPRS_SM_SMREG_PDP_ACTIVATE_SEC, "PDP_ACTIVATE_SEC" },
+ { OSMO_GPRS_SM_SMREG_MBMS_ACTIVATE, "MBMS_ACTIVATE" },
+ { 0, NULL }
+};
+
+const char *osmo_gprs_sm_prim_name(const struct osmo_gprs_sm_prim *sm_prim)
+{
+ static char name_buf[256];
+ const char *sap = osmo_gprs_sm_prim_sap_name(sm_prim->oph.sap);
+ const char *op = get_value_string(osmo_prim_op_names, sm_prim->oph.operation);
+ const char *type;
+
+ switch (sm_prim->oph.sap) {
+ case OSMO_GPRS_SM_SAP_SMREG:
+ type = osmo_gprs_sm_smreg_prim_type_name(sm_prim->oph.primitive);
+ break;
+ default:
+ type = "unsupported-sm-sap";
+ }
+
+ snprintf(name_buf, sizeof(name_buf), "%s-%s.%s", sap, type, op);
+ return name_buf;
+}
+
+static int sm_up_cb_dummy(struct osmo_gprs_sm_prim *sm_prim, void *user_data)
+{
+ LOGSM(LOGL_INFO, "%s(%s)\n", __func__, osmo_gprs_sm_prim_name(sm_prim));
+ return 0;
+}
+
+static int sm_down_cb_dummy(struct osmo_gprs_sm_prim *sm_prim, void *user_data)
+{
+ LOGSM(LOGL_INFO, "%s(%s)\n", __func__, osmo_gprs_sm_prim_name(sm_prim));
+ return 0;
+}
+
+static int sm_gmm_down_cb_dummy(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data)
+{
+ LOGSM(LOGL_INFO, "%s(%s)\n", __func__, osmo_gprs_gmm_prim_name(gmm_prim));
+ return 0;
+}
+
+/* Set callback used by SM layer to push primitives to higher layers in protocol stack */
+void osmo_gprs_sm_prim_set_up_cb(osmo_gprs_sm_prim_up_cb up_cb, void *up_user_data)
+{
+ g_ctx->sm_up_cb = up_cb;
+ g_ctx->sm_up_cb_user_data = up_user_data;
+}
+
+/* Set callback used by SM layer to push primitives to lower layers in protocol stack */
+void osmo_gprs_sm_prim_set_down_cb(osmo_gprs_sm_prim_down_cb down_cb, void *down_user_data)
+{
+ g_ctx->sm_down_cb = down_cb;
+ g_ctx->sm_down_cb_user_data = down_user_data;
+}
+
+/* Set callback used by SM layer to push primitives to GMM lower layer in protocol stack */
+void osmo_gprs_sm_prim_set_gmm_down_cb(osmo_gprs_sm_prim_gmm_down_cb gmm_down_cb, void *gmm_down_user_data)
+{
+ g_ctx->sm_gmm_down_cb = gmm_down_cb;
+ g_ctx->sm_gmm_down_cb_user_data = gmm_down_user_data;
+}
+
+/********************************
+ * Primitive allocation:
+ ********************************/
+
+/* allocate a msgb containing a struct osmo_gprs_sm_prim + optional l3 data */
+static struct msgb *gprs_sm_prim_msgb_alloc(unsigned int npdu_len)
+{
+ const int headroom = SM_MSGB_HEADROOM;
+ const int size = headroom + sizeof(struct osmo_gprs_sm_prim) + npdu_len;
+ struct msgb *msg = msgb_alloc_headroom(size, headroom, "sm_prim");
+
+ if (!msg)
+ return NULL;
+
+ msg->l1h = msgb_put(msg, sizeof(struct osmo_gprs_sm_prim));
+
+ return msg;
+}
+
+struct osmo_gprs_sm_prim *gprs_sm_prim_alloc(unsigned int sap, unsigned int type,
+ enum osmo_prim_operation operation,
+ unsigned int extra_size)
+{
+ struct msgb *msg = gprs_sm_prim_msgb_alloc(extra_size);
+ struct osmo_gprs_sm_prim *sm_prim = msgb_sm_prim(msg);
+
+ osmo_prim_init(&sm_prim->oph, sap, type, operation, msg);
+ return sm_prim;
+}
+
+/*** SMREG ***/
+
+static inline struct osmo_gprs_sm_prim *sm_prim_smreg_alloc(enum osmo_gprs_sm_smreg_prim_type type,
+ enum osmo_prim_operation operation,
+ unsigned int extra_size)
+{
+ return gprs_sm_prim_alloc(OSMO_GPRS_SM_SAP_SMREG, type, operation, extra_size);
+}
+
+/* TS 24.007 6.5.1.1 SMREG-PDP-ACTIVATE-REQ */
+struct osmo_gprs_sm_prim *osmo_gprs_sm_prim_alloc_smreg_pdp_act_req(void)
+{
+ struct osmo_gprs_sm_prim *sm_prim;
+ sm_prim = sm_prim_smreg_alloc(OSMO_GPRS_SM_SMREG_PDP_ACTIVATE, PRIM_OP_REQUEST, 0);
+ return sm_prim;
+}
+
+
+/* TS 24.007 6.5.1.2 SMREG-PDP-ACTIVATE-CNF */
+struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_act_cnf(void)
+{
+ struct osmo_gprs_sm_prim *sm_prim;
+ sm_prim = sm_prim_smreg_alloc(OSMO_GPRS_SM_SMREG_PDP_ACTIVATE, PRIM_OP_CONFIRM, 0);
+ sm_prim->smreg.pdp_act_cnf.accepted = true;
+ /* TODO: sm_prim->smreg.pdp_act_cnf.acc.* */
+ return sm_prim;
+}
+/* TODO: TS 24.007 6.5.1.3 SMREG-PDP-ACTIVATE-REJ */
+
+/* TS 24.007 6.5.1.4 SMREG-PDP-ACTIVATE-IND */
+struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_act_ind(void)
+{
+ struct osmo_gprs_sm_prim *sm_prim;
+ sm_prim = sm_prim_smreg_alloc(OSMO_GPRS_SM_SMREG_PDP_ACTIVATE, PRIM_OP_INDICATION, 0);
+ return sm_prim;
+}
+
+static int gprs_sm_prim_handle_unsupported(struct osmo_gprs_sm_prim *sm_prim)
+{
+ LOGSM(LOGL_ERROR, "Unsupported sm_prim! %s\n", osmo_gprs_sm_prim_name(sm_prim));
+ msgb_free(sm_prim->oph.msg);
+ return -ENOTSUP;
+}
+
+static int gprs_sm_prim_handle_gmm_unsupported(struct osmo_gprs_gmm_prim *gmm_prim)
+{
+ LOGSM(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_sm_prim_call_up_cb(struct osmo_gprs_sm_prim *sm_prim)
+{
+ int rc;
+ if (g_ctx->sm_up_cb)
+ rc = g_ctx->sm_up_cb(sm_prim, g_ctx->sm_up_cb_user_data);
+ else
+ rc = sm_up_cb_dummy(sm_prim, g_ctx->sm_up_cb_user_data);
+ msgb_free(sm_prim->oph.msg);
+ return rc;
+}
+
+/* TS 24.007 6.6.1.1 SMREG-Attach.request:*/
+static int gprs_sm_prim_handle_smreg_pdp_act_req(struct osmo_gprs_sm_prim *sm_prim)
+{
+ int rc = 0;
+ struct gprs_sm_ms *ms;
+ struct gprs_sm_entity *sme = NULL;
+ struct osmo_gprs_sm_smreg_prim *smreg = &sm_prim->smreg;
+
+ OSMO_ASSERT(smreg->pdp_act_req.qos_len <= sizeof(sme->qos));
+ OSMO_ASSERT(smreg->pdp_act_req.pco_len <= sizeof(sme->pco));
+
+ ms = gprs_sm_find_ms_by_id(smreg->ms_id);
+ if (!ms) {
+ ms = gprs_sm_ms_alloc(smreg->ms_id);
+ OSMO_ASSERT(ms);
+ } else {
+ sme = gprs_sm_ms_get_pdp_ctx(ms, smreg->pdp_act_req.nsapi);
+ LOGSME(sme, LOGL_ERROR, "Rx SMREG-PDP-ACT.req for already existing PDP context\n");
+ return -EINVAL;
+ }
+
+ sme = gprs_sm_entity_alloc(ms, smreg->pdp_act_req.nsapi);
+ OSMO_ASSERT(sme);
+
+ if (smreg->pdp_act_req.llc_sapi != OSMO_GPRS_SM_LLC_SAPI_UNASSIGNED)
+ sme->llc_sapi = smreg->pdp_act_req.llc_sapi;
+ else
+ sme->llc_sapi = OSMO_GPRS_SM_LLC_SAPI_SAPI3; /* default */
+
+ sme->pdp_addr_ietf_type = smreg->pdp_act_req.pdp_addr_ietf_type;
+ memcpy(&sme->pdp_addr_v4, &smreg->pdp_act_req.pdp_addr_v4, sizeof(sme->pdp_addr_v4));
+ memcpy(&sme->pdp_addr_v6, &smreg->pdp_act_req.pdp_addr_v6, sizeof(sme->pdp_addr_v6));
+
+ OSMO_STRLCPY_ARRAY(sme->apn, smreg->pdp_act_req.apn);
+
+ sme->qos_len = smreg->pdp_act_req.qos_len;
+ if (sme->qos_len > 0)
+ memcpy(&sme->qos, &smreg->pdp_act_req.qos, sme->qos_len);
+
+ sme->pco_len = smreg->pdp_act_req.pco_len;
+ if (sme->pco_len > 0)
+ memcpy(&sme->pco, &smreg->pdp_act_req.pco, sme->pco_len);
+
+ /* Info required to establish GMM: */
+ ms->gmm.ptmsi = sm_prim->smreg.pdp_act_req.gmm.ptmsi;
+ if (sm_prim->smreg.pdp_act_req.gmm.imsi[0] != '\0')
+ OSMO_STRLCPY_ARRAY(ms->gmm.imsi, sm_prim->smreg.pdp_act_req.gmm.imsi);
+ if (sm_prim->smreg.pdp_act_req.gmm.imei[0] != '\0')
+ OSMO_STRLCPY_ARRAY(ms->gmm.imei, sm_prim->smreg.pdp_act_req.gmm.imei);
+ if (sm_prim->smreg.pdp_act_req.gmm.imeisv[0] != '\0')
+ OSMO_STRLCPY_ARRAY(ms->gmm.imeisv, sm_prim->smreg.pdp_act_req.gmm.imeisv);
+
+ rc = osmo_fsm_inst_dispatch(sme->ms_fsm.fi, GPRS_SM_MS_EV_TX_ACT_PDP_CTX_REQ, NULL);
+
+ return rc;
+}
+
+static int gprs_sm_prim_handle_smreg(struct osmo_gprs_sm_prim *sm_prim)
+{
+ int rc;
+
+ switch (OSMO_PRIM_HDR(&sm_prim->oph)) {
+ case OSMO_PRIM(OSMO_GPRS_SM_SMREG_PDP_ACTIVATE, PRIM_OP_REQUEST):
+ rc = gprs_sm_prim_handle_smreg_pdp_act_req(sm_prim);
+ break;
+ default:
+ rc = gprs_sm_prim_handle_unsupported(sm_prim);
+ }
+ return rc;
+}
+
+/* SM higher layers push SM primitive down to SM layer: */
+int osmo_gprs_sm_prim_upper_down(struct osmo_gprs_sm_prim *sm_prim)
+{
+ int rc;
+
+ LOGSM(LOGL_INFO, "Rx from upper layers: %s\n", osmo_gprs_sm_prim_name(sm_prim));
+
+
+ switch (sm_prim->oph.sap) {
+ case OSMO_GPRS_SM_SAP_SMREG:
+ rc = gprs_sm_prim_handle_smreg(sm_prim);
+ break;
+ default:
+ rc = gprs_sm_prim_handle_unsupported(sm_prim);
+ rc = 1;
+ }
+
+ /* Special return value '1' means: do not free */
+ if (rc != 1)
+ msgb_free(sm_prim->oph.msg);
+ else
+ rc = 0;
+ return rc;
+}
+
+/********************************
+ * Handling from/to lower layers:
+ ********************************/
+
+int gprs_sm_prim_call_down_cb(struct osmo_gprs_sm_prim *sm_prim)
+{
+ int rc;
+ if (g_ctx->sm_down_cb)
+ rc = g_ctx->sm_down_cb(sm_prim, g_ctx->sm_down_cb_user_data);
+ else
+ rc = sm_down_cb_dummy(sm_prim, g_ctx->sm_down_cb_user_data);
+ msgb_free(sm_prim->oph.msg);
+ return rc;
+}
+
+/* SM lower layers (GMM) push SM primitive up to SM layer: */
+int osmo_gprs_sm_prim_lower_up(struct osmo_gprs_sm_prim *sm_prim)
+{
+ OSMO_ASSERT(g_ctx);
+ OSMO_ASSERT(sm_prim);
+ struct msgb *msg = sm_prim->oph.msg;
+ int rc;
+
+ LOGSM(LOGL_INFO, "Rx from lower layers: %s\n", osmo_gprs_sm_prim_name(sm_prim));
+
+ switch (sm_prim->oph.sap) {
+ default:
+ rc = gprs_sm_prim_handle_unsupported(sm_prim);
+ rc = 1;
+ }
+
+ /* Special return value '1' means: do not free */
+ if (rc != 1)
+ msgb_free(msg);
+ else
+ rc = 0;
+ return rc;
+}
+
+int gprs_sm_prim_call_gmm_down_cb(struct osmo_gprs_gmm_prim *gmm_prim)
+{
+ int rc;
+ if (g_ctx->sm_gmm_down_cb)
+ rc = g_ctx->sm_gmm_down_cb(gmm_prim, g_ctx->sm_gmm_down_cb_user_data);
+ else
+ rc = sm_gmm_down_cb_dummy(gmm_prim, g_ctx->sm_gmm_down_cb_user_data);
+ /* Special return value '1' means: do not free */
+ if (rc != 1)
+ msgb_free(gmm_prim->oph.msg);
+ else
+ rc = 0;
+ return rc;
+}
+
+/* TS 24.007 9.5.1.2 GMMSM-ESTABLISH-CNF */
+static int gprs_sm_prim_handle_gmmsm_establish_cnf(struct osmo_gprs_gmm_prim *gmm_prim)
+{
+ struct osmo_gprs_gmm_gmmsm_prim *gmmsm = &gmm_prim->gmmsm;
+ struct gprs_sm_entity *sme;
+ int rc, ev;
+
+ sme = gprs_sm_find_sme_by_sess_id(gmmsm->sess_id);
+ if (!sme) {
+ LOGSM(LOGL_ERROR, "Rx GMMSM-ESTABLISH.cnf for non existing SM Entity\n");
+ return -EINVAL;
+ }
+
+ ev = gmmsm->establish_cnf.accepted ?
+ GPRS_SM_MS_EV_RX_GMM_ESTABLISH_CNF : GPRS_SM_MS_EV_RX_GMM_ESTABLISH_REJ;
+ rc = osmo_fsm_inst_dispatch(sme->ms_fsm.fi, ev, NULL);
+
+ return rc;
+}
+
+/* TS 24.007 9.5.1.6 GMMSM-UNITDATA-IND */
+static int gprs_sm_prim_handle_gmmsm_unitdata_ind(struct osmo_gprs_gmm_prim *gmm_prim)
+{
+ struct osmo_gprs_gmm_gmmsm_prim *gmmsm = &gmm_prim->gmmsm;
+ struct gprs_sm_entity *sme;
+ int rc;
+
+ sme = gprs_sm_find_sme_by_sess_id(gmmsm->sess_id);
+ if (!sme) {
+ LOGSM(LOGL_ERROR, "Rx GMMSM-UNITDATA.ind for non existing SM Entity\n");
+ return -EINVAL;
+ }
+
+ rc = gprs_sm_rx(sme,
+ (struct gsm48_hdr *)gmm_prim->gmmsm.unitdata_ind.smpdu,
+ gmm_prim->gmmsm.unitdata_ind.smpdu_len);
+
+ return rc;
+}
+
+static int gprs_sm_prim_handle_gmmsm(struct osmo_gprs_gmm_prim *gmm_prim)
+{
+ int rc = 0;
+ switch (OSMO_PRIM_HDR(&gmm_prim->oph)) {
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_ESTABLISH, PRIM_OP_CONFIRM):
+ rc = gprs_sm_prim_handle_gmmsm_establish_cnf(gmm_prim);
+ break;
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_UNITDATA, PRIM_OP_INDICATION):
+ rc = gprs_sm_prim_handle_gmmsm_unitdata_ind(gmm_prim);
+ break;
+ default:
+ rc = gprs_sm_prim_handle_gmm_unsupported(gmm_prim);
+ rc = 1;
+ break;
+ }
+ return rc;
+}
+
+/* SM lower layers (GMM) push SM primitive up to SM layer: */
+int osmo_gprs_sm_prim_gmm_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;
+
+ LOGSM(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_GMMSM:
+ rc = gprs_sm_prim_handle_gmmsm(gmm_prim);
+ break;
+ default:
+ rc = gprs_sm_prim_handle_gmm_unsupported(gmm_prim);
+ rc = 1;
+ }
+
+ /* Special return value '1' means: do not free */
+ if (rc != 1)
+ msgb_free(msg);
+ else
+ rc = 0;
+ return rc;
+}
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9447b2d..d890847 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -3,6 +3,7 @@
llc \
rlcmac \
sndcp \
+ sm \
$(NULL)
# The `:;' works around a Bash 3.2 bug when the output is not writeable.
diff --git a/tests/gmm/gmm_prim_test.c b/tests/gmm/gmm_prim_test.c
index 70f8377..0053b94 100644
--- a/tests/gmm/gmm_prim_test.c
+++ b/tests/gmm/gmm_prim_test.c
@@ -158,6 +158,23 @@
OSMO_ASSERT(0)
}
break;
+ case OSMO_GPRS_GMM_SAP_GMMSM:
+ switch (OSMO_PRIM_HDR(&gmm_prim->oph)) {
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_ESTABLISH, PRIM_OP_CONFIRM):
+ printf("%s(): Rx %s sess_id=%u accepted=%u rej_cause=%u\n", __func__, pdu_name,
+ gmm_prim->gmmsm.sess_id,
+ gmm_prim->gmmsm.establish_cnf.accepted,
+ gmm_prim->gmmsm.establish_cnf.rej.cause);
+ break;
+ //case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_DETACH, PRIM_OP_CONFIRM):
+ // printf("%s(): Rx %s detach_type='%s'\n", __func__, pdu_name,
+ // osmo_gprs_gmm_detach_ms_type_name(gmm_prim->gmmsm.detach_cnf.detach_type));
+ // break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0)
+ }
+ break;
default:
printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
OSMO_ASSERT(0);
@@ -202,7 +219,8 @@
return 0;
}
-static void test_gmm_prim_ms(void)
+/* Test explicit GPRS attach through GMMREG, TS 24.007 Annex C.1 */
+static void test_gmm_prim_ms_gmmreg(void)
{
struct osmo_gprs_gmm_prim *gmm_prim;
struct osmo_gprs_llc_prim *llc_prim;
@@ -254,6 +272,7 @@
rc = osmo_gprs_gmm_prim_llc_lower_up(llc_prim);
OSMO_ASSERT(rc == 0);
/* As a result, MS answers GMM Attach Complete */
+ /* As a result, MS submits GMMREG ATTACH.cnf */
/* ... */
@@ -276,6 +295,70 @@
printf("==== %s() [end] ====\n", __func__);
}
+/* Test implicit GPRS attach through SM (ACT PDP CTX), TS 24.007 Annex C.3 */
+static void test_gmm_prim_ms_gmmsm(void)
+{
+ struct osmo_gprs_gmm_prim *gmm_prim;
+ struct osmo_gprs_llc_prim *llc_prim;
+ int rc;
+ uint32_t ptmsi = 0x00000000;
+ uint32_t tlli = 0x00000000;
+ char *imsi = "1234567890";
+ char *imei = "42342342342342";
+ char *imeisv = "4234234234234275";
+ uint32_t sess_id = 1234;
+
+ printf("==== %s() [start] ====\n", __func__);
+
+ rc = osmo_gprs_gmm_init(OSMO_GPRS_GMM_LOCATION_MS);
+ OSMO_ASSERT(rc == 0);
+ osmo_gprs_gmm_enable_gprs(true);
+
+ 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);
+ osmo_gprs_gmm_prim_set_llc_down_cb(test_gmm_prim_llc_down_cb, NULL);
+
+ /* MS sends primitive to active a PDP ctx: */
+ gmm_prim = osmo_gprs_gmm_prim_alloc_gmmsm_establish_req(sess_id);
+ OSMO_ASSERT(gmm_prim);
+ gmm_prim->gmmsm.establish_req.attach_type = OSMO_GPRS_GMM_ATTACH_TYPE_GPRS;
+ gmm_prim->gmmsm.establish_req.ptmsi = ptmsi;
+ OSMO_STRLCPY_ARRAY(gmm_prim->gmmsm.establish_req.imsi, imsi);
+ OSMO_STRLCPY_ARRAY(gmm_prim->gmmsm.establish_req.imei, imei);
+ OSMO_STRLCPY_ARRAY(gmm_prim->gmmsm.establish_req.imeisv, imeisv);
+ rc = osmo_gprs_gmm_prim_upper_down(gmm_prim);
+ OSMO_ASSERT(rc == 0);
+ /* MS sends GMM Attach Req first since its not eyt attached */
+
+ /* Network answers with GMM Identity Req: */
+ llc_prim = gprs_llc_prim_alloc_ll_unitdata_ind(tlli, OSMO_GPRS_LLC_SAPI_GMM, (uint8_t *)pdu_gmm_identity_req, sizeof(pdu_gmm_identity_req));
+ OSMO_ASSERT(llc_prim);
+ rc = osmo_gprs_gmm_prim_llc_lower_up(llc_prim);
+ OSMO_ASSERT(rc == 0);
+ /* As a result, MS answers GMM Identity Resp */
+
+ /* Network sends GMM Ciph Auth Req */
+ llc_prim = gprs_llc_prim_alloc_ll_unitdata_ind(tlli, OSMO_GPRS_LLC_SAPI_GMM, (uint8_t *)pdu_gmm_auth_ciph_req, sizeof(pdu_gmm_auth_ciph_req));
+ OSMO_ASSERT(llc_prim);
+ rc = osmo_gprs_gmm_prim_llc_lower_up(llc_prim);
+ OSMO_ASSERT(rc == 0);
+ /* As a result, MS answers GMM Ciph Auth Resp */
+
+ /* Network sends GMM Attach Accept */
+ llc_prim = gprs_llc_prim_alloc_ll_unitdata_ind(tlli, OSMO_GPRS_LLC_SAPI_GMM, (uint8_t *)pdu_gmm_att_acc, sizeof(pdu_gmm_att_acc));
+ OSMO_ASSERT(llc_prim);
+ rc = osmo_gprs_gmm_prim_llc_lower_up(llc_prim);
+ OSMO_ASSERT(rc == 0);
+ /* As a result, MS answers GMM Attach Complete */
+ /* As a result, MS submits GMMSM Establish.cnf */
+
+ /* ... */
+
+ /* DEACT: TODO */
+
+ 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,
@@ -296,7 +379,8 @@
log_set_print_level(osmo_stderr_target, 1);
log_set_use_color(osmo_stderr_target, 0);
- test_gmm_prim_ms();
+ test_gmm_prim_ms_gmmreg();
+ test_gmm_prim_ms_gmmsm();
talloc_free(tall_ctx);
}
diff --git a/tests/gmm/gmm_prim_test.err b/tests/gmm/gmm_prim_test.err
index 8e50caa..12d39da 100644
--- a/tests/gmm/gmm_prim_test.err
+++ b/tests/gmm/gmm_prim_test.err
@@ -2,8 +2,8 @@
DLGLOBAL INFO GMM_MS{Null}: Allocated
DLGLOBAL INFO GMM_MS{Null}: Received Event ENABLE_GPRS_MODE
DLGLOBAL INFO GMM_MS{Null}: state_chg to Deregistered
-DLGLOBAL INFO GMME(PTMSI-00000000) Tx GMM ATTACH REQUEST (new P-TMSI=0x00000000)
DLGLOBAL INFO GMM_MS{Deregistered}: Received Event ATTACH_REQUESTED
+DLGLOBAL INFO GMME(PTMSI-00000000) Tx GMM ATTACH REQUEST (new P-TMSI=0x00000000)
DLGLOBAL INFO GMM_MS{Deregistered}: state_chg to RegisteredInitiated
DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication
DLGLOBAL DEBUG GMME(PTMSI-00000000) Rx GMM IDENTITY REQUEST mi_type=IMEI
@@ -24,3 +24,23 @@
DLGLOBAL DEBUG GMME(PTMSI-ea711b41) Rx GMM DETACH ACCEPT (MO) force_standby_indicated=false
DLGLOBAL INFO GMM_MS{DeregisteredInitiated}: Received Event DETACH_ACCEPTED
DLGLOBAL INFO GMM_MS{DeregisteredInitiated}: state_chg to Deregistered
+DLGLOBAL DEBUG GMME(PTMSI-ffffffff) free()
+DLGLOBAL INFO GMM_MS{Deregistered}: Deallocated
+DLGLOBAL INFO Rx from upper layers: GMMSM-ESTABLISH.request
+DLGLOBAL INFO GMM_MS{Null}: Allocated
+DLGLOBAL INFO GMM_MS{Null}: Received Event ENABLE_GPRS_MODE
+DLGLOBAL INFO GMM_MS{Null}: state_chg to Deregistered
+DLGLOBAL INFO GMM_MS{Deregistered}: Received Event ATTACH_REQUESTED
+DLGLOBAL INFO GMME(PTMSI-00000000) Tx GMM ATTACH REQUEST (new P-TMSI=0x00000000)
+DLGLOBAL INFO GMM_MS{Deregistered}: state_chg to RegisteredInitiated
+DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication
+DLGLOBAL DEBUG GMME(PTMSI-00000000) Rx GMM IDENTITY REQUEST mi_type=IMEI
+DLGLOBAL INFO GMME(PTMSI-00000000) Tx GMM IDENTITY RESPONSE
+DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication
+DLGLOBAL DEBUG GMME(PTMSI-00000000) Rx GMM AUTHENTICATION AND CIPHERING REQUEST
+DLGLOBAL INFO GMME(PTMSI-00000000) Tx GMM GMM AUTHENTICATION AND CIPHERING RESPONSE
+DLGLOBAL INFO Rx from lower layers: LL-UNITDATA.indication
+DLGLOBAL DEBUG GMME(PTMSI-00000000) Rx GMM ATTACH ACCEPT
+DLGLOBAL INFO GMME(PTMSI-ea711b41) Tx GMM ATTACH COMPL
+DLGLOBAL INFO GMM_MS{RegisteredInitiated}: Received Event ATTACH_ACCEPTED
+DLGLOBAL INFO GMM_MS{RegisteredInitiated}: state_chg to Registered
diff --git a/tests/gmm/gmm_prim_test.ok b/tests/gmm/gmm_prim_test.ok
index ed4f7e1..dbbb858 100644
--- a/tests/gmm/gmm_prim_test.ok
+++ b/tests/gmm/gmm_prim_test.ok
@@ -1,13 +1,23 @@
-==== test_gmm_prim_ms() [start] ====
+==== test_gmm_prim_ms_gmmreg() [start] ====
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 01 04 97 07 00 00 01 0a 00 05 f4 00 00 00 00 00 f0 00 00 00 00 00 ]
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 16 08 42 32 24 43 32 24 43 f2 ]
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 13 02 ]
test_gmm_prim_llc_down_cb(): Rx LLGM-ASSIGN.request TLLI=0x00000000
-test_gmm_prim_up_cb(): Rx GMMREG-ATTACH.confirm accepted=1 rej_cause=0
test_gmm_prim_llc_down_cb(): Rx LLGM-ASSIGN.request TLLI=0x00000000
test_gmm_prim_down_cb(): Rx GMRR-ASSIGN.request new_tlli=0xea711b41
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=[08 03 ]
+test_gmm_prim_up_cb(): Rx GMMREG-ATTACH.confirm accepted=1 rej_cause=0
test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=[08 05 20 0a 00 05 f4 ea 71 1b 41 ]
test_gmm_prim_llc_down_cb(): Rx LLGM-ASSIGN.request TLLI=0x00000000
test_gmm_prim_up_cb(): Rx GMMREG-DETACH.confirm detach_type='GPRS detach'
-==== test_gmm_prim_ms() [end] ====
+==== test_gmm_prim_ms_gmmreg() [end] ====
+==== test_gmm_prim_ms_gmmsm() [start] ====
+test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 01 04 97 07 00 00 01 0a 00 05 f4 00 00 00 00 00 f0 00 00 00 00 00 ]
+test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 16 08 42 32 24 43 32 24 43 f2 ]
+test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0x00000000 SAPI=GMM l3=[08 13 02 ]
+test_gmm_prim_llc_down_cb(): Rx LLGM-ASSIGN.request TLLI=0x00000000
+test_gmm_prim_llc_down_cb(): Rx LLGM-ASSIGN.request TLLI=0x00000000
+test_gmm_prim_down_cb(): Rx GMRR-ASSIGN.request new_tlli=0xea711b41
+test_gmm_prim_llc_down_cb(): Rx LL-UNITDATA.request TLLI=0xea711b41 SAPI=GMM l3=[08 03 ]
+test_gmm_prim_up_cb(): Rx GMMSM-ESTABLISH.confirm sess_id=1234 accepted=1 rej_cause=0
+==== test_gmm_prim_ms_gmmsm() [end] ====
diff --git a/tests/sm/Makefile.am b/tests/sm/Makefile.am
new file mode 100644
index 0000000..f9df676
--- /dev/null
+++ b/tests/sm/Makefile.am
@@ -0,0 +1,33 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/include/ \
+ $(NULL)
+
+AM_CFLAGS = \
+ -Wall \
+ $(LIBOSMOGSM_CFLAGS) \
+ $(LIBOSMOCORE_CFLAGS) \
+ $(NULL)
+
+AM_LDFLAGS = \
+ -no-install \
+ $(NULL)
+
+check_PROGRAMS = \
+ sm_prim_test \
+ $(NULL)
+
+EXTRA_DIST = \
+ sm_prim_test.err \
+ sm_prim_test.ok \
+ $(NULL)
+
+# libosmo-gprs-gmm.a is used below to access non-exported private symbols used in the test:
+# libosmo-gprs-gmm.a requires libosmo-gprs-llc.la
+sm_prim_test_SOURCES = sm_prim_test.c
+sm_prim_test_LDADD = \
+ $(top_builddir)/src/sm/libosmo-gprs-sm.la \
+ $(top_builddir)/src/gmm/.libs/libosmo-gprs-gmm.a \
+ $(top_builddir)/src/llc/.libs/libosmo-gprs-llc.la \
+ $(LIBOSMOGSM_LIBS) \
+ $(LIBOSMOCORE_LIBS) \
+ $(NULL)
diff --git a/tests/sm/sm_prim_test.c b/tests/sm/sm_prim_test.c
new file mode 100644
index 0000000..5703985
--- /dev/null
+++ b/tests/sm/sm_prim_test.c
@@ -0,0 +1,283 @@
+/* sm_prim tests
+ *
+ * (C) 2023 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de>
+ * Author: Pau espin Pedrol <pespin(a)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/fsm.h>
+#include <osmocom/core/msgb.h>
+
+#include <osmocom/gprs/gmm/gmm_prim.h>
+#include <osmocom/gprs/gmm/gmm_private.h>
+#include <osmocom/gprs/sm/sm.h>
+#include <osmocom/gprs/sm/sm_prim.h>
+
+static void *tall_ctx = NULL;
+
+static uint32_t last_gmm_establish_sess_id = 0;
+
+/*
+GSM A-I/F DTAP - Activate PDP Context Accept
+ Protocol Discriminator: GPRS session management messages (10)
+ .... 1010 = Protocol discriminator: GPRS session management messages (0xa)
+ 1... .... = TI flag: allocated by receiver
+ .000 .... = TIO: 0
+ 01.. .... = Sequence number: 1
+ DTAP GPRS Session Management Message Type: Activate PDP Context Accept (0x42)
+ LLC Service Access Point Identifier - Negotiated LLC SAPI
+ 0000 .... = Spare bit(s): 0
+ .... 0011 = LLC SAPI: SAPI 3 (3)
+ Quality Of Service - Negotiated QoS
+ Length: 14
+ 00.. .... = Spare bit(s): 0
+ ..10 0... = Quality of Service Delay class: Delay class 4 (best effort) (4)
+ .... .011 = Reliability class: Unacknowledged GTP/LLC, Ack RLC, Protected data (3)
+ 0110 .... = Peak throughput: Up to 32 000 octet/s (6)
+ .... 0... = Spare bit(s): 0
+ .... .010 = Precedence class: Normal priority (2)
+ 000. .... = Spare bit(s): 0
+ ...1 1111 = Mean throughput: Best effort (31)
+ 011. .... = Traffic class: Interactive class (3)
+ ...1 0... = Delivery order: Without delivery order ('no') (2)
+ .... .010 = Delivery of erroneous SDUs: Erroneous SDUs are delivered('yes') (2)
+ Maximum SDU size: 1520 octets (153)
+ Maximum bitrate for uplink: 63 kbps (63)
+ Maximum bitrate for downlink: 63 kbps (63)
+ 0001 .... = Residual Bit Error Rate (BER): 5*10-2 (1)
+ .... 0001 = SDU error ratio: 1*10-2 (1)
+ 0100 00.. = Transfer delay: 200 ms (16)
+ .... ..11 = Traffic handling priority: Priority level 3 (3)
+ Guaranteed bitrate for uplink: 0 kbps (255)
+ Guaranteed bitrate for downlink: 0 kbps (255)
+ 000. .... = Spare bit(s): 0
+ ...0 .... = Signalling indication: Not optimised for signalling traffic
+ .... 0000 = Source statistics description: unknown (0)
+ Maximum bitrate for downlink (extended): Use the value indicated by the Maximum bit rate for downlink (0)
+ Guaranteed bitrate for downlink (extended): Use the value indicated by the Guaranteed bit rate for downlink (0)
+ Radio Priority
+ .... .100 = Radio Priority (PDP or SMS): priority level 4 (lowest) (4)
+ Packet Data Protocol Address - PDP address
+ Element ID: 0x2b
+ Length: 6
+ 0000 .... = Spare bit(s): 0
+ .... 0001 = PDP type organization: IETF allocated address (1)
+ PDP type number: IPv4 address (33)
+ IPv4 address: 176.16.222.2
+ Protocol Configuration Options
+ Element ID: 0x27
+ Length: 20
+ [Link direction: Network to MS (1)]
+ 1... .... = Extension: True
+ .... .000 = Configuration Protocol: PPP for use with IP PDP type or IP PDN type (0)
+ Protocol or Container ID: Internet Protocol Control Protocol (0x8021)
+ Length: 0x10 (16)
+ PPP IP Control Protocol
+ Code: Configuration Ack (2)
+ Identifier: 0 (0x00)
+ Length: 16
+ Options: (12 bytes), Primary DNS Server IP Address, Secondary DNS Server IP Address
+ Primary DNS Server IP Address
+ Type: Primary DNS Server IP Address (129)
+ Length: 6
+ Primary DNS Address: 8.8.8.8
+ Secondary DNS Server IP Address
+ Type: Secondary DNS Server IP Address (131)
+ Length: 6
+ Secondary DNS Address: 8.8.8.4
+*/
+
+static uint8_t pdu_sm_act_pdp_ctx_acc[] = {
+0x8a, 0x42, 0x03, 0x0e, 0x23, 0x62, 0x1f, 0x72,
+0x99, 0x3f, 0x3f, 0x11, 0x43, 0xff, 0xff, 0x00,
+0x00, 0x00, 0x04, 0x2b, 0x06, 0x01, 0x21, 0xb0,
+0x10, 0xde, 0x02, 0x27, 0x14, 0x80, 0x80, 0x21,
+0x10, 0x02, 0x00, 0x00, 0x10, 0x81, 0x06, 0x08,
+0x08, 0x08, 0x08, 0x83, 0x06, 0x08, 0x08, 0x08,
+0x04
+};
+
+int test_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);
+
+ 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):
+ printf("%s(): Rx %s\n", __func__, pdu_name);
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0)
+ }
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0);
+ }
+ return 0;
+}
+
+int test_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);
+
+ 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_REQUEST):
+ printf("%s(): Rx %s\n", __func__, pdu_name);
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0)
+ }
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0);
+ }
+ return 0;
+}
+
+int test_sm_prim_gmm_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) {
+ case OSMO_GPRS_GMM_SAP_GMMSM:
+ switch (OSMO_PRIM_HDR(&gmm_prim->oph)) {
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_ESTABLISH, PRIM_OP_REQUEST):
+ printf("%s(): Rx %s sess_id=%u\n", __func__, pdu_name,
+ gmm_prim->gmmsm.sess_id);
+ last_gmm_establish_sess_id = gmm_prim->gmmsm.sess_id;
+ break;
+ case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_UNITDATA, PRIM_OP_REQUEST):
+ printf("%s(): Rx %s sess_id=%u SMPDU=[%s]\n", __func__, pdu_name,
+ gmm_prim->gmmsm.sess_id,
+ osmo_hexdump(gmm_prim->gmmsm.unitdata_req.smpdu,
+ gmm_prim->gmmsm.unitdata_req.smpdu_len));
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0);
+ }
+ break;
+ case OSMO_GPRS_GMM_SAP_GMMRR:
+ printf("%s(): Rx %s\n", __func__, pdu_name);
+ break;
+ default:
+ printf("%s(): Unexpected Rx %s\n", __func__, pdu_name);
+ OSMO_ASSERT(0);
+ }
+ return 0;
+}
+
+static void test_sm_prim_ms(void)
+{
+ struct osmo_gprs_sm_prim *sm_prim;
+ struct osmo_gprs_gmm_prim *gmm_prim;
+ int rc;
+ 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};
+ char apn[OSMO_GPRS_SM_APN_MAXLEN] = "apn";
+ uint32_t ptmsi = 0x00000000;
+ char *imsi = "1234567890";
+ char *imei = "42342342342342";
+ char *imeisv = "4234234234234275";
+
+ printf("==== %s() [start] ====\n", __func__);
+
+ rc = osmo_gprs_sm_init(OSMO_GPRS_SM_LOCATION_MS);
+ OSMO_ASSERT(rc == 0);
+
+ osmo_gprs_sm_prim_set_up_cb(test_sm_prim_up_cb, NULL);
+ osmo_gprs_sm_prim_set_down_cb(test_sm_prim_down_cb, NULL);
+ osmo_gprs_sm_prim_set_gmm_down_cb(test_sm_prim_gmm_down_cb, NULL);
+
+ /* MS sends SM PDP Act Req (GMMSM-ESTABLISH.req is submitted down to GMM layer) */
+ sm_prim = osmo_gprs_sm_prim_alloc_smreg_pdp_act_req();
+ OSMO_ASSERT(sm_prim);
+ 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 = OSMO_GPRS_SM_PDP_ADDR_IETF_IPV4;
+ sm_prim->smreg.pdp_act_req.pdp_addr_v4 = 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);
+ 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);
+ rc = osmo_gprs_sm_prim_upper_down(sm_prim);
+ OSMO_ASSERT(rc == 0);
+
+ /* GMM internaly does GMM Attach and confirms it is attached to SM: */
+ gmm_prim = gprs_gmm_prim_alloc_gmmsm_establish_cnf(last_gmm_establish_sess_id, 0);
+ OSMO_ASSERT(gmm_prim);
+ rc = osmo_gprs_sm_prim_gmm_lower_up(gmm_prim);
+ OSMO_ASSERT(rc == 0);
+
+ /* SM layer is now sending GMMSM-UNITDATA.req with the Active Pdp Context Req... */
+ /* Network accepts the pdp ctx req with Activate Pdp Context Accept: */
+ gmm_prim = gprs_gmm_prim_alloc_gmmsm_unitdata_ind(last_gmm_establish_sess_id,
+ (uint8_t *)pdu_sm_act_pdp_ctx_acc,
+ sizeof(pdu_sm_act_pdp_ctx_acc));
+ OSMO_ASSERT(gmm_prim);
+ rc = osmo_gprs_sm_prim_gmm_lower_up(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:");
+ osmo_fsm_log_addr(false);
+
+ 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_sm_prim_ms();
+
+ talloc_free(tall_ctx);
+}
diff --git a/tests/sm/sm_prim_test.err b/tests/sm/sm_prim_test.err
new file mode 100644
index 0000000..d9dc296
--- /dev/null
+++ b/tests/sm/sm_prim_test.err
@@ -0,0 +1,11 @@
+DLGLOBAL INFO Rx from upper layers: SMREG-PDP_ACTIVATE.request
+DLGLOBAL INFO SM_MS{INACTIVE}: Allocated
+DLGLOBAL INFO SM_MS{INACTIVE}: Received Event TX_ACT_PDP_CTX_REQ
+DLGLOBAL INFO SM_MS{INACTIVE}: state_chg to PDP_ACTIVE_PENDING
+DLGLOBAL INFO Rx from lower layers: GMMSM-ESTABLISH.confirm
+DLGLOBAL INFO SM_MS{PDP_ACTIVE_PENDING}: Received Event RX GMM_ESTABLISH_CNF
+DLGLOBAL INFO PDP(ID-0:NSAPI-6) Tx SM Activate PDP Context Request
+DLGLOBAL INFO Rx from lower layers: GMMSM-UNITDATA.indication
+DLGLOBAL INFO PDP(ID-0:NSAPI-6) Rx SM Activate PDP Context Accept
+DLGLOBAL INFO SM_MS{PDP_ACTIVE_PENDING}: Received Event RX_ACT_PDP_CTX_ACC
+DLGLOBAL INFO SM_MS{PDP_ACTIVE_PENDING}: state_chg to PDP_ACTIVE
diff --git a/tests/sm/sm_prim_test.ok b/tests/sm/sm_prim_test.ok
new file mode 100644
index 0000000..82d4a97
--- /dev/null
+++ b/tests/sm/sm_prim_test.ok
@@ -0,0 +1,5 @@
+==== test_sm_prim_ms() [start] ====
+test_sm_prim_gmm_down_cb(): Rx GMMSM-ESTABLISH.request sess_id=0
+test_sm_prim_gmm_down_cb(): Rx GMMSM-UNITDATA.request sess_id=0 SMPDU=[8a 41 06 03 01 00 06 10 21 00 00 00 00 28 04 27 01 00 ]
+test_sm_prim_up_cb(): Rx SMREG-PDP_ACTIVATE.confirm
+==== test_sm_prim_ms() [end] ====
diff --git a/tests/testsuite.at b/tests/testsuite.at
index cfe25d4..55a54d7 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -57,6 +57,13 @@
AT_CHECK([$abs_top_builddir/tests/rlcmac/rlcmac_prim_test], [0], [expout], [experr])
AT_CLEANUP
+AT_SETUP([sm/sm_prim])
+AT_KEYWORDS([sm sm_prim])
+cat $abs_srcdir/sm/sm_prim_test.ok > expout
+cat $abs_srcdir/sm/sm_prim_test.err > experr
+AT_CHECK([$abs_top_builddir/tests/sm/sm_prim_test], [0], [expout], [experr])
+AT_CLEANUP
+
AT_SETUP([sndcp/sndcp_prim])
AT_KEYWORDS([sndcp sndcp_prim])
cat $abs_srcdir/sndcp/sndcp_prim_test.ok > expout
--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32154
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I9b4a9a6364f7799540475e7e1d10ab2310768281
Gerrit-Change-Number: 32154
Gerrit-PatchSet: 3
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: merged
1
0
[S] Change in libosmo-gprs[master]: rlcmac: gprs_rlcmac_tbf_free():Call proper free function for DL TBF
by pespin 31 Mar '23
by pespin 31 Mar '23
31 Mar '23
pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32122 )
Change subject: rlcmac: gprs_rlcmac_tbf_free():Call proper free function for DL TBF
......................................................................
rlcmac: gprs_rlcmac_tbf_free():Call proper free function for DL TBF
Change-Id: I65c37dd4ea20f039680e0927722b332d1140e62e
---
M src/rlcmac/tbf.c
1 file changed, 12 insertions(+), 1 deletion(-)
Approvals:
Jenkins Builder: Verified
fixeria: Looks good to me, approved
diff --git a/src/rlcmac/tbf.c b/src/rlcmac/tbf.c
index c82f0ea..a88e924 100644
--- a/src/rlcmac/tbf.c
+++ b/src/rlcmac/tbf.c
@@ -21,6 +21,7 @@
#include <osmocom/gprs/rlcmac/tbf.h>
#include <osmocom/gprs/rlcmac/tbf_ul.h>
+#include <osmocom/gprs/rlcmac/tbf_dl.h>
#include <osmocom/gprs/rlcmac/gre.h>
#include <osmocom/gprs/rlcmac/pdch_ul_controller.h>
@@ -43,5 +44,6 @@
{
if (tbf->direction == GPRS_RLCMAC_TBF_DIR_UL)
gprs_rlcmac_ul_tbf_free(tbf_as_ul_tbf(tbf));
- /* else: TODO dl_tbf not yet implemented */
+ else
+ gprs_rlcmac_dl_tbf_free(tbf_as_dl_tbf(tbf));
}
--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32122
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I65c37dd4ea20f039680e0927722b332d1140e62e
Gerrit-Change-Number: 32122
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: merged
1
0
[M] Change in libosmo-gprs[master]: rlcmac: Fix DL_ASS polls removed when UL TBF released
by pespin 31 Mar '23
by pespin 31 Mar '23
31 Mar '23
pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32118 )
Change subject: rlcmac: Fix DL_ASS polls removed when UL TBF released
......................................................................
rlcmac: Fix DL_ASS polls removed when UL TBF released
The DL_TBF for the assignment is not created until later on when the
DL_TBF is first used, only the DL_ASS request is stored as part of the
gpre->tbf_dl_ass_fsm.
Since no DL_TBF existed, the POLL was being stored if the DL_ASS
referred the UL_TBF by means of GlobalTFI->ULTBF.
Instead, let's not require an UL_TBF to be present and simply pass the
GRE along which can be used to send the PKT_CTRL_ACK later on when the
scheduling the poll triggers.
Change-Id: Icdaa30e9ff942fb53cc4bbd801e4542b8885b32a
---
M include/osmocom/gprs/rlcmac/gre.h
M include/osmocom/gprs/rlcmac/pdch_ul_controller.h
M include/osmocom/gprs/rlcmac/tbf.h
M src/rlcmac/gre.c
M src/rlcmac/pdch_ul_controller.c
M src/rlcmac/rlcmac.c
M src/rlcmac/sched.c
M src/rlcmac/tbf.c
M tests/rlcmac/rlcmac_prim_test.err
9 files changed, 79 insertions(+), 56 deletions(-)
Approvals:
Jenkins Builder: Verified
fixeria: Looks good to me, but someone else must approve
pespin: Looks good to me, approved
diff --git a/include/osmocom/gprs/rlcmac/gre.h b/include/osmocom/gprs/rlcmac/gre.h
index 8322cf7..358d0aa 100644
--- a/include/osmocom/gprs/rlcmac/gre.h
+++ b/include/osmocom/gprs/rlcmac/gre.h
@@ -31,5 +31,7 @@
int gprs_rlcmac_entity_llc_enqueue(struct gprs_rlcmac_entity *gre, uint8_t *ll_pdu, unsigned int ll_pdu_len,
enum osmo_gprs_rlcmac_llc_sapi sapi, uint8_t radio_prio);
+struct msgb *gprs_rlcmac_gre_create_pkt_ctrl_ack(const struct gprs_rlcmac_entity *gre);
+
#define LOGGRE(gre, level, fmt, args...) \
LOGRLCMAC(level, "GRE(%08x) " fmt, (gre)->tlli, ## args)
diff --git a/include/osmocom/gprs/rlcmac/pdch_ul_controller.h b/include/osmocom/gprs/rlcmac/pdch_ul_controller.h
index 52970c4..1dcc1db 100644
--- a/include/osmocom/gprs/rlcmac/pdch_ul_controller.h
+++ b/include/osmocom/gprs/rlcmac/pdch_ul_controller.h
@@ -21,7 +21,8 @@
#include <osmocom/core/linuxrbtree.h>
#include <osmocom/core/utils.h>
-struct gprs_rlcmac_dl_tbf;
+struct gprs_rlcmac_gre;
+struct gprs_rlcmac_tbf;
struct gprs_rlcmac_pdch_ulc {
uint8_t ts_nr;
@@ -43,12 +44,16 @@
struct rb_node node; /*! entry in gprs_rlcmac_pdch_ulc->tree_root */
uint32_t fn;
enum gprs_rlcmac_pdch_ulc_poll_reason reason;
- struct gprs_rlcmac_tbf *tbf;
+ union {
+ struct gprs_rlcmac_tbf *tbf;
+ struct gprs_rlcmac_entity *gre;
+ void *data;
+ };
};
struct gprs_rlcmac_pdch_ulc *gprs_rlcmac_pdch_ulc_alloc(void *ctx, uint8_t ts_nr);
-int gprs_rlcmac_pdch_ulc_reserve(struct gprs_rlcmac_pdch_ulc *ulc, uint32_t fn, enum gprs_rlcmac_pdch_ulc_poll_reason reason, struct gprs_rlcmac_tbf *tbf);
+int gprs_rlcmac_pdch_ulc_reserve(struct gprs_rlcmac_pdch_ulc *ulc, uint32_t fn, enum gprs_rlcmac_pdch_ulc_poll_reason reason, void *data);
struct gprs_rlcmac_pdch_ulc_node *gprs_rlcmac_pdch_ulc_get_node(struct gprs_rlcmac_pdch_ulc *ulc, uint32_t fn);
struct gprs_rlcmac_pdch_ulc_node *gprs_rlcmac_pdch_ulc_pop_node(struct gprs_rlcmac_pdch_ulc *ulc, uint32_t fn);
diff --git a/include/osmocom/gprs/rlcmac/tbf.h b/include/osmocom/gprs/rlcmac/tbf.h
index 83a887d..9130237 100644
--- a/include/osmocom/gprs/rlcmac/tbf.h
+++ b/include/osmocom/gprs/rlcmac/tbf.h
@@ -28,8 +28,6 @@
void gprs_rlcmac_tbf_free(struct gprs_rlcmac_tbf *tbf);
-struct msgb *gprs_rlcmac_tbf_create_pkt_ctrl_ack(const struct gprs_rlcmac_tbf *tbf);
-
#define LOGPTBF(tbf, lvl, fmt, args...) \
LOGP(g_rlcmac_log_cat[tbf->direction == GPRS_RLCMAC_TBF_DIR_DL ? \
OSMO_GPRS_RLCMAC_LOGC_TBFDL : \
diff --git a/src/rlcmac/gre.c b/src/rlcmac/gre.c
index 87953c1..2bab3c1 100644
--- a/src/rlcmac/gre.c
+++ b/src/rlcmac/gre.c
@@ -21,6 +21,10 @@
#include <stdbool.h>
+#include <osmocom/core/bitvec.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
#include <osmocom/gprs/rlcmac/rlcmac.h>
#include <osmocom/gprs/rlcmac/rlcmac_prim.h>
#include <osmocom/gprs/rlcmac/rlcmac_private.h>
@@ -29,6 +33,7 @@
#include <osmocom/gprs/rlcmac/tbf_ul_fsm.h>
#include <osmocom/gprs/rlcmac/tbf_ul.h>
#include <osmocom/gprs/rlcmac/gre.h>
+#include <osmocom/gprs/rlcmac/rlcmac_enc.h>
struct gprs_rlcmac_entity *gprs_rlcmac_entity_alloc(uint32_t tlli)
{
@@ -131,3 +136,38 @@
return rc;
}
+
+struct msgb *gprs_rlcmac_gre_create_pkt_ctrl_ack(const struct gprs_rlcmac_entity *gre)
+{
+ struct msgb *msg;
+ struct bitvec bv;
+ RlcMacUplink_t ul_block;
+ int rc;
+
+ OSMO_ASSERT(gre);
+
+ msg = msgb_alloc(GSM_MACBLOCK_LEN, "pkt_ctrl_ack");
+ if (!msg)
+ return NULL;
+
+ /* Initialize a bit vector that uses allocated msgb as the data buffer. */
+ bv = (struct bitvec){
+ .data = msgb_put(msg, GSM_MACBLOCK_LEN),
+ .data_len = GSM_MACBLOCK_LEN,
+ };
+ bitvec_unhex(&bv, GPRS_RLCMAC_DUMMY_VEC);
+
+ gprs_rlcmac_enc_prepare_pkt_ctrl_ack(&ul_block, gre->tlli);
+ rc = osmo_gprs_rlcmac_encode_uplink(&bv, &ul_block);
+ if (rc < 0) {
+ LOGGRE(gre, LOGL_ERROR, "Encoding of Packet Control ACK failed (%d)\n", rc);
+ goto free_ret;
+ }
+ LOGGRE(gre, LOGL_DEBUG, "Tx Packet Control Ack\n");
+
+ return msg;
+
+free_ret:
+ msgb_free(msg);
+ return NULL;
+}
diff --git a/src/rlcmac/pdch_ul_controller.c b/src/rlcmac/pdch_ul_controller.c
index 731caf0..7c5e41a 100644
--- a/src/rlcmac/pdch_ul_controller.c
+++ b/src/rlcmac/pdch_ul_controller.c
@@ -124,11 +124,11 @@
int gprs_rlcmac_pdch_ulc_reserve(struct gprs_rlcmac_pdch_ulc *ulc, uint32_t fn,
enum gprs_rlcmac_pdch_ulc_poll_reason reason,
- struct gprs_rlcmac_tbf *tbf)
+ void *data)
{
struct gprs_rlcmac_pdch_ulc_node *item = _alloc_node(ulc, fn);
item->reason = reason;
- item->tbf = tbf;
+ item->data = data;
LOGRLCMAC(LOGL_DEBUG, "Register POLL (TS=%u FN=%u, reason=%s)\n",
ulc->ts_nr, item->fn,
get_value_string(gprs_rlcmac_pdch_ulc_poll_reason_names, item->reason));
diff --git a/src/rlcmac/rlcmac.c b/src/rlcmac/rlcmac.c
index 8ff6c68..574ff5a 100644
--- a/src/rlcmac/rlcmac.c
+++ b/src/rlcmac/rlcmac.c
@@ -400,12 +400,12 @@
};
rc = gprs_rlcmac_tbf_start_from_pacch(&gre->dl_tbf_dl_ass_fsm, &ev_data);
- if (tbf && dl_block->SP) {
+ if (dl_block->SP) {
uint32_t poll_fn = rrbp2fn(rlcmac_prim->l1ctl.pdch_data_ind.fn, dl_block->RRBP);
gprs_rlcmac_pdch_ulc_reserve(g_ctx->sched.ulc[rlcmac_prim->l1ctl.pdch_data_ind.ts_nr],
poll_fn,
GPRS_RLCMAC_PDCH_ULC_POLL_DL_ASS,
- tbf);
+ gre);
}
return rc;
}
diff --git a/src/rlcmac/sched.c b/src/rlcmac/sched.c
index 46e43ab..50a3910 100644
--- a/src/rlcmac/sched.c
+++ b/src/rlcmac/sched.c
@@ -38,7 +38,7 @@
struct gprs_rlcmac_ul_tbf *poll_ul_ack_new_ul_tbf; /* 9.3.2.4.2 (answer with PKT RES REQ) */
struct gprs_rlcmac_ul_tbf *poll_ul_ack; /* 11.2.2 (answer with PKT CTRL ACK) */
struct gprs_rlcmac_ul_tbf *poll_ul_ass; /* (answer Pkt UL ASS with PKT CTRL ACK) */
- struct gprs_rlcmac_tbf *poll_dl_ass; /* (answer Pkt DL ASS with PKT CTRL ACK) */
+ struct gprs_rlcmac_entity *poll_dl_ass; /* (answer Pkt DL ASS with PKT CTRL ACK) */
struct gprs_rlcmac_ul_tbf *ul_ass; /* PCU grants USF/SBA: transmit Pkt Res Req (2phase access)*/
};
@@ -80,7 +80,7 @@
tbfs->poll_ul_ass = tbf_as_ul_tbf(node->tbf);
break;
case GPRS_RLCMAC_PDCH_ULC_POLL_DL_ASS:
- tbfs->poll_dl_ass = node->tbf;
+ tbfs->poll_dl_ass = node->gre;
break;
case GPRS_RLCMAC_PDCH_ULC_POLL_UL_ACK:
/* TS 44.060: 9.3.2.4.2 If the PACKET UPLINK ACK/NACK message
@@ -199,7 +199,7 @@
if (tbfs->poll_ul_ack) {
LOGRLCMAC(LOGL_DEBUG, "(ts=%u,fn=%u,usf=%u) Tx Pkt Control Ack (UL ACK/NACK poll)\n",
bi->ts, bi->fn, bi->usf);
- msg = gprs_rlcmac_tbf_create_pkt_ctrl_ack(ul_tbf_as_tbf(tbfs->poll_ul_ack));
+ msg = gprs_rlcmac_gre_create_pkt_ctrl_ack(ul_tbf_as_tbf(tbfs->poll_ul_ack)->gre);
/* Last UL message, freeing */
gprs_rlcmac_ul_tbf_free(tbfs->poll_ul_ack);
return msg;
@@ -207,14 +207,14 @@
if (tbfs->poll_dl_ass) {
LOGRLCMAC(LOGL_DEBUG, "(ts=%u,fn=%u,usf=%u) Tx Pkt Control Ack (DL ASS poll)\n",
bi->ts, bi->fn, bi->usf);
- msg = gprs_rlcmac_tbf_create_pkt_ctrl_ack(tbfs->poll_dl_ass);
+ msg = gprs_rlcmac_gre_create_pkt_ctrl_ack(tbfs->poll_dl_ass);
if (msg)
return msg;
}
if (tbfs->poll_ul_ass) {
LOGRLCMAC(LOGL_DEBUG, "(ts=%u,fn=%u,usf=%u) Tx Pkt Control Ack (UL ASS poll)\n",
bi->ts, bi->fn, bi->usf);
- msg = gprs_rlcmac_tbf_create_pkt_ctrl_ack(ul_tbf_as_tbf(tbfs->poll_ul_ass));
+ msg = gprs_rlcmac_gre_create_pkt_ctrl_ack(ul_tbf_as_tbf(tbfs->poll_ul_ass)->gre);
if (msg)
return msg;
}
diff --git a/src/rlcmac/tbf.c b/src/rlcmac/tbf.c
index 524740d..c82f0ea 100644
--- a/src/rlcmac/tbf.c
+++ b/src/rlcmac/tbf.c
@@ -19,14 +19,9 @@
*
*/
-#include <osmocom/core/bitvec.h>
-#include <osmocom/core/msgb.h>
-#include <osmocom/gsm/protocol/gsm_04_08.h>
-
#include <osmocom/gprs/rlcmac/tbf.h>
#include <osmocom/gprs/rlcmac/tbf_ul.h>
#include <osmocom/gprs/rlcmac/gre.h>
-#include <osmocom/gprs/rlcmac/rlcmac_enc.h>
#include <osmocom/gprs/rlcmac/pdch_ul_controller.h>
void gprs_rlcmac_tbf_constructor(struct gprs_rlcmac_tbf *tbf,
@@ -50,38 +45,3 @@
gprs_rlcmac_ul_tbf_free(tbf_as_ul_tbf(tbf));
/* else: TODO dl_tbf not yet implemented */
}
-
-struct msgb *gprs_rlcmac_tbf_create_pkt_ctrl_ack(const struct gprs_rlcmac_tbf *tbf)
-{
- struct msgb *msg;
- struct bitvec bv;
- RlcMacUplink_t ul_block;
- int rc;
-
- OSMO_ASSERT(tbf);
-
- msg = msgb_alloc(GSM_MACBLOCK_LEN, "pkt_ctrl_ack");
- if (!msg)
- return NULL;
-
- /* Initialize a bit vector that uses allocated msgb as the data buffer. */
- bv = (struct bitvec){
- .data = msgb_put(msg, GSM_MACBLOCK_LEN),
- .data_len = GSM_MACBLOCK_LEN,
- };
- bitvec_unhex(&bv, GPRS_RLCMAC_DUMMY_VEC);
-
- gprs_rlcmac_enc_prepare_pkt_ctrl_ack(&ul_block, tbf->gre->tlli);
- rc = osmo_gprs_rlcmac_encode_uplink(&bv, &ul_block);
- if (rc < 0) {
- LOGPTBF(tbf, LOGL_ERROR, "Encoding of Packet Control ACK failed (%d)\n", rc);
- goto free_ret;
- }
- LOGPTBF(tbf, LOGL_DEBUG, "Tx Packet Control Ack\n");
-
- return msg;
-
-free_ret:
- msgb_free(msg);
- return NULL;
-}
diff --git a/tests/rlcmac/rlcmac_prim_test.err b/tests/rlcmac/rlcmac_prim_test.err
index f0b55d0..e7edbca 100644
--- a/tests/rlcmac/rlcmac_prim_test.err
+++ b/tests/rlcmac/rlcmac_prim_test.err
@@ -61,7 +61,7 @@
DLGLOBAL DEBUG Register POLL (TS=7 FN=21, reason=UL_ACK)
DLGLOBAL DEBUG Rx from lower layers: L1CTL-PDCH_RTS.indication
DLGLOBAL DEBUG (ts=7,fn=21,usf=0) Tx Pkt Control Ack (UL ACK/NACK poll)
-DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00002342) Tx Packet Control Ack
+DLGLOBAL DEBUG GRE(00002342) Tx Packet Control Ack
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
DLGLOBAL INFO UL_TBF{RELEASING}: Deallocated
DLGLOBAL DEBUG Tx to lower layers: L1CTL-PDCH_DATA.request
@@ -755,7 +755,7 @@
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
DLGLOBAL DEBUG Rx from lower layers: L1CTL-PDCH_RTS.indication
DLGLOBAL DEBUG (ts=7,fn=43,usf=2) Tx Pkt Control Ack (UL ASS poll)
-DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) Tx Packet Control Ack
+DLGLOBAL DEBUG GRE(00000001) Tx Packet Control Ack
DLGLOBAL DEBUG Tx to lower layers: L1CTL-PDCH_DATA.request
DLGLOBAL DEBUG Rx from lower layers: L1CTL-PDCH_RTS.indication
DLGLOBAL DEBUG TBF(UL:NR-0:TLLI-00000001) Sending new block at BSN 0, CS=CS-2
--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32118
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: Icdaa30e9ff942fb53cc4bbd801e4542b8885b32a
Gerrit-Change-Number: 32118
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann(a)sysmocom.de>
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: merged
1
0
[M] Change in libosmo-gprs[master]: rlcmac: Release UL_TBF L1CTL resources upon free
by pespin 31 Mar '23
by pespin 31 Mar '23
31 Mar '23
pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32123 )
Change subject: rlcmac: Release UL_TBF L1CTL resources upon free
......................................................................
rlcmac: Release UL_TBF L1CTL resources upon free
Change-Id: I4c98d5431a8409a6d428e96f9bfbb442bd75b24f
---
M src/rlcmac/tbf_ul_fsm.c
M tests/rlcmac/rlcmac_prim_test.err
M tests/rlcmac/rlcmac_prim_test.ok
3 files changed, 71 insertions(+), 27 deletions(-)
Approvals:
Jenkins Builder: Verified
fixeria: Looks good to me, approved
diff --git a/src/rlcmac/tbf_ul_fsm.c b/src/rlcmac/tbf_ul_fsm.c
index e49e6dc..9bf708c 100644
--- a/src/rlcmac/tbf_ul_fsm.c
+++ b/src/rlcmac/tbf_ul_fsm.c
@@ -69,12 +69,15 @@
return ul_slotmask;
}
-static int configure_ul_tbf(struct gprs_rlcmac_tbf_ul_fsm_ctx *ctx)
+static int configure_ul_tbf(struct gprs_rlcmac_tbf_ul_fsm_ctx *ctx, bool release)
{
struct osmo_gprs_rlcmac_prim *rlcmac_prim;
- uint8_t ul_slotmask = ul_tbf_ul_slotmask(ctx->ul_tbf);
+ uint8_t ul_slotmask;
- LOGPFSML(ctx->fi, LOGL_INFO, "Send L1CTL-CF_UL_TBF.req ul_slotmask=0x%02x\n", ul_slotmask);
+ ul_slotmask = release ? 0 : ul_tbf_ul_slotmask(ctx->ul_tbf);
+
+ LOGPFSML(ctx->fi, LOGL_INFO, "Send L1CTL-CF_UL_TBF.req ul_tbf_nr=%u ul_slotmask=0x%02x %s\n",
+ ctx->tbf->nr, ul_slotmask, release ? "(release)" : "(reconf)");
rlcmac_prim = gprs_rlcmac_prim_alloc_l1ctl_cfg_ul_tbf_req(ctx->tbf->nr, ul_slotmask);
return gprs_rlcmac_prim_call_down_cb(rlcmac_prim);
}
@@ -124,7 +127,7 @@
/* Mark everything we transmitted so far as NACKed: */
gprs_rlcmac_rlc_ul_window_mark_for_resend(ctx->ul_tbf->ulw);
/* Make sure the lower layers realize this tbf_nr has no longer any assigned resource: */
- configure_ul_tbf(ctx);
+ configure_ul_tbf(ctx, false);
}
static void st_new(struct osmo_fsm_inst *fi, uint32_t event, void *data)
@@ -145,7 +148,7 @@
switch (event) {
case GPRS_RLCMAC_TBF_UL_EV_UL_ASS_COMPL:
/* Configure UL TBF on the lower MAC side: */
- configure_ul_tbf(ctx);
+ configure_ul_tbf(ctx, false);
tbf_ul_fsm_state_chg(fi, GPRS_RLCMAC_TBF_UL_ST_FLOW);
break;
default:
@@ -243,6 +246,7 @@
}
}
+/* Waiting for scheduler to transmit PKT CTRL ACK for the already received UL ACK/NACK FinalAck=1 */
static void st_releasing(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
//struct gprs_rlcmac_tbf_ul_fsm_ctx *ctx = (struct gprs_rlcmac_tbf_ul_fsm_ctx *)fi->priv;
@@ -379,6 +383,10 @@
void gprs_rlcmac_tbf_ul_fsm_destructor(struct gprs_rlcmac_ul_tbf *ul_tbf)
{
struct gprs_rlcmac_tbf_ul_fsm_ctx *ctx = &ul_tbf->state_fsm;
+
+ /* Make sure the lower layers realize this tbf_nr has no longer any assigned resource: */
+ configure_ul_tbf(ctx, true);
+
osmo_fsm_inst_free(ctx->fi);
ctx->fi = NULL;
}
diff --git a/tests/rlcmac/rlcmac_prim_test.err b/tests/rlcmac/rlcmac_prim_test.err
index e7edbca..abc6209 100644
--- a/tests/rlcmac/rlcmac_prim_test.err
+++ b/tests/rlcmac/rlcmac_prim_test.err
@@ -15,7 +15,7 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -63,6 +63,8 @@
DLGLOBAL DEBUG (ts=7,fn=21,usf=0) Tx Pkt Control Ack (UL ACK/NACK poll)
DLGLOBAL DEBUG GRE(00002342) Tx Packet Control Ack
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
+DLGLOBAL INFO UL_TBF{RELEASING}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (release)
+DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{RELEASING}: Deallocated
DLGLOBAL DEBUG Tx to lower layers: L1CTL-PDCH_DATA.request
DLGLOBAL INFO DL_TBF_ASS{IDLE}: Deallocated
@@ -83,14 +85,14 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
DLGLOBAL INFO UL_TBF{FLOW}: Timeout of T3164
DLGLOBAL INFO UL_TBF{FLOW}: T3164 timeout attempts=1
DLGLOBAL INFO UL_TBF{FLOW}: state_chg to NEW
-DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x00
+DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START
DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START
@@ -104,14 +106,14 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
DLGLOBAL INFO UL_TBF{FLOW}: Timeout of T3164
DLGLOBAL INFO UL_TBF{FLOW}: T3164 timeout attempts=2
DLGLOBAL INFO UL_TBF{FLOW}: state_chg to NEW
-DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x00
+DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START
DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START
@@ -125,14 +127,14 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
DLGLOBAL INFO UL_TBF{FLOW}: Timeout of T3164
DLGLOBAL INFO UL_TBF{FLOW}: T3164 timeout attempts=3
DLGLOBAL INFO UL_TBF{FLOW}: state_chg to NEW
-DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x00
+DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START
DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START
@@ -146,7 +148,7 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -154,6 +156,8 @@
DLGLOBAL INFO UL_TBF{FLOW}: T3164 timeout attempts=4
DLGLOBAL NOTICE UL_TBF{FLOW}: TBF establishment failure (T3164 timeout attempts=4)
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
+DLGLOBAL INFO UL_TBF{FLOW}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (release)
+DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{FLOW}: Deallocated
DLGLOBAL INFO DL_TBF_ASS{IDLE}: Deallocated
DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request
@@ -173,7 +177,7 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -194,7 +198,7 @@
DLGLOBAL INFO UL_TBF{FLOW}: Timeout of T3166
DLGLOBAL INFO UL_TBF{FLOW}: T3166 timeout attempts=1
DLGLOBAL INFO UL_TBF{FLOW}: state_chg to NEW
-DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x00
+DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START
DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START
@@ -208,7 +212,7 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -226,7 +230,7 @@
DLGLOBAL INFO UL_TBF{FLOW}: Timeout of T3166
DLGLOBAL INFO UL_TBF{FLOW}: T3166 timeout attempts=2
DLGLOBAL INFO UL_TBF{FLOW}: state_chg to NEW
-DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x00
+DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START
DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START
@@ -240,7 +244,7 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -258,7 +262,7 @@
DLGLOBAL INFO UL_TBF{FLOW}: Timeout of T3166
DLGLOBAL INFO UL_TBF{FLOW}: T3166 timeout attempts=3
DLGLOBAL INFO UL_TBF{FLOW}: state_chg to NEW
-DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x00
+DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START
DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START
@@ -272,7 +276,7 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -291,6 +295,8 @@
DLGLOBAL INFO UL_TBF{FLOW}: T3166 timeout attempts=4
DLGLOBAL NOTICE UL_TBF{FLOW}: TBF establishment failure (T3166 timeout attempts=4)
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
+DLGLOBAL INFO UL_TBF{FLOW}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (release)
+DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{FLOW}: Deallocated
DLGLOBAL INFO DL_TBF_ASS{IDLE}: Deallocated
DLGLOBAL DEBUG Rx from lower layers: L1CTL-CCCH_DATA.indication
@@ -312,7 +318,7 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -411,7 +417,7 @@
DLGLOBAL NOTICE TBF(UL:NR-0:TLLI-00002342) N3104_MAX (9) reached
DLGLOBAL INFO UL_TBF{FINISHED}: Received Event N3104_MAX
DLGLOBAL INFO UL_TBF{FINISHED}: state_chg to NEW
-DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x00
+DLGLOBAL INFO UL_TBF{NEW}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Received Event START
DLGLOBAL INFO UL_TBF{NEW}: Received Event UL_ASS_START
@@ -426,12 +432,14 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
DLGLOBAL INFO DL_TBF_ASS{IDLE}: Deallocated
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
+DLGLOBAL INFO UL_TBF{FLOW}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (release)
+DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{FLOW}: Deallocated
DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request
DLGLOBAL INFO TLLI=0x00002342 not found, creating entity on the fly
@@ -450,7 +458,7 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -492,6 +500,8 @@
DLGLOBAL DEBUG Tx to lower layers: L1CTL-PDCH_DATA.request
DLGLOBAL INFO UL_TBF{FINISHED}: Timeout of T3182
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
+DLGLOBAL INFO UL_TBF{FINISHED}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (release)
+DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{FINISHED}: Deallocated
DLGLOBAL INFO DL_TBF_ASS{IDLE}: Deallocated
DLGLOBAL INFO Rx from upper layers: GRR-UNITDATA.request
@@ -511,7 +521,7 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -596,6 +606,8 @@
DLGLOBAL INFO UL_TBF{FINISHED}: Last UL block sent (CV=0), start T3182
DLGLOBAL NOTICE UL_TBF{FINISHED}: TBF establishment failure (Data block with CV=0 retransmit attempts=4)
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
+DLGLOBAL INFO UL_TBF{FINISHED}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (release)
+DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{FINISHED}: Deallocated
DLGLOBAL DEBUG Tx to lower layers: L1CTL-PDCH_DATA.request
DLGLOBAL INFO DL_TBF_ASS{IDLE}: Deallocated
@@ -616,7 +628,7 @@
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: ImmAss DynamicAlloc (1phase access) ts_nr=7 usf=0
DLGLOBAL INFO UL_TBF_ASS{WAIT_CCCH_IMM_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0x80
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x80 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -659,12 +671,16 @@
DLGLOBAL INFO UL_TBF{NEW}: state_chg to ASSIGN
DLGLOBAL INFO UL_TBF_ASS{IDLE}: state_chg to SCHED_PKT_RES_REQ
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
+DLGLOBAL INFO UL_TBF{RELEASING}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (release)
+DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{RELEASING}: Deallocated
DLGLOBAL INFO UL_TBF_ASS{SCHED_PKT_RES_REQ}: Received Event CREATE_RLCMAC_MSG
DLGLOBAL INFO UL_TBF_ASS{SCHED_PKT_RES_REQ}: state_chg to WAIT_PKT_UL_ASS
DLGLOBAL DEBUG Tx to lower layers: L1CTL-PDCH_DATA.request
DLGLOBAL INFO DL_TBF_ASS{IDLE}: Deallocated
DLGLOBAL INFO UL_TBF_ASS{WAIT_PKT_UL_ASS}: Deallocated
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=1 ul_slotmask=0x00 (release)
+DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: Deallocated
DLGLOBAL INFO Rx from upper layers: GMMRR-ASSIGN.request
DLGLOBAL INFO GMMRR-ASSIGN.req: creating new entity TLLI=0x00000001
@@ -749,7 +765,7 @@
DLGLOBAL DEBUG Register POLL (TS=7 FN=43, reason=UL_ASS)
DLGLOBAL INFO UL_TBF_ASS{WAIT_PKT_UL_ASS}: state_chg to COMPLETED
DLGLOBAL INFO UL_TBF{ASSIGN}: Received Event UL_ASS_COMPL
-DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_slotmask=0xc0
+DLGLOBAL INFO UL_TBF{ASSIGN}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0xc0 (reconf)
DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{ASSIGN}: state_chg to FLOW
DLGLOBAL INFO UL_TBF_ASS{COMPLETED}: state_chg to IDLE
@@ -777,4 +793,6 @@
DLGLOBAL INFO DL_TBF_ASS{IDLE}: Deallocated
DLGLOBAL INFO DL_TBF{FINISHED}: Deallocated
DLGLOBAL INFO UL_TBF_ASS{IDLE}: Deallocated
+DLGLOBAL INFO UL_TBF{FINISHED}: Send L1CTL-CF_UL_TBF.req ul_tbf_nr=0 ul_slotmask=0x00 (release)
+DLGLOBAL DEBUG Tx to lower layers: L1CTL-CFG_UL_TBF.request
DLGLOBAL INFO UL_TBF{FINISHED}: Deallocated
diff --git a/tests/rlcmac/rlcmac_prim_test.ok b/tests/rlcmac/rlcmac_prim_test.ok
index 7028547..71b9888 100644
--- a/tests/rlcmac/rlcmac_prim_test.ok
+++ b/tests/rlcmac/rlcmac_prim_test.ok
@@ -4,6 +4,7 @@
test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x80
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=4 ts=7 data_len=34 data=[3c 01 01 00 00 23 42 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 00 00 00 00 71 62 f2 24 6c 84 44 04 00 ]
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=8 ts=7 data_len=34 data=[00 01 02 1d 00 00 23 42 11 e5 10 00 e2 18 f2 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ]
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x00
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=21 ts=7 data_len=23 data=[40 04 00 00 8d 08 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b ]
=== test_ul_tbf_attach end ===
=== test_ul_tbf_t3164_timeout start ===
@@ -27,6 +28,7 @@
test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x80
sys={20.000000}, mono={20.000000}: clock_override_add
sys={20.000000}, mono={20.000000}: Expect T3164 timeout
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x00
=== test_ul_tbf_t3164_timeout end ===
=== test_ul_tbf_t3166_timeout start ===
sys={0.000000}, mono={0.000000}: clock_override_set
@@ -53,6 +55,7 @@
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=4 ts=7 data_len=34 data=[3c 01 01 00 00 23 42 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 00 00 00 00 71 62 f2 24 6c 84 44 04 00 ]
sys={20.000000}, mono={20.000000}: clock_override_add
sys={20.000000}, mono={20.000000}: Expect T3166 timeout
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x00
=== test_ul_tbf_t3166_timeout end ===
=== test_ul_tbf_n3104_timeout start ===
sys={0.000000}, mono={0.000000}: clock_override_set
@@ -80,6 +83,7 @@
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=43 ts=7 data_len=34 data=[3c 01 01 00 00 23 42 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 00 00 00 00 71 62 f2 24 6c 84 44 04 00 ]
test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x80
=== test_ul_tbf_n3104_timeout end ===
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x00
=== test_ul_tbf_t3182_timeout start ===
sys={0.000000}, mono={0.000000}: clock_override_set
test_rlcmac_prim_down_cb(): Rx L1CTL-RACH.request ra=0x7a
@@ -88,6 +92,7 @@
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=8 ts=7 data_len=34 data=[00 00 02 1d 11 e5 10 00 e2 18 f2 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ]
sys={5.000000}, mono={5.000000}: clock_override_add
sys={5.000000}, mono={5.000000}: Expect T3182 timeout
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x00
=== test_ul_tbf_t3182_timeout end ===
=== test_ul_tbf_last_data_cv0_retrans_max start ===
sys={0.000000}, mono={0.000000}: clock_override_set
@@ -102,6 +107,7 @@
RTS 2: FN=21
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=21 ts=7 data_len=34 data=[00 00 02 1d 11 e5 10 00 e2 18 f2 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ]
RTS 3: FN=26
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x00
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=26 ts=7 data_len=34 data=[00 00 02 1d 11 e5 10 00 e2 18 f2 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ]
=== test_ul_tbf_last_data_cv0_retrans_max end ===
=== test_ul_tbf_request_another_ul_tbf start ===
@@ -109,8 +115,10 @@
test_rlcmac_prim_down_cb(): Rx L1CTL-RACH.request ra=0x7b
test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x80
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=4 ts=7 data_len=34 data=[00 01 00 39 00 00 23 42 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ]
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x00
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=17 ts=7 data_len=23 data=[40 16 40 00 08 d0 a0 bc 00 00 00 00 00 00 70 00 38 00 00 2b 2b 2b 2b ]
=== test_ul_tbf_request_another_ul_tbf end ===
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=1 ul_slotmask=0x00
=== test_dl_tbf_ccch_assign start ===
sys={0.000000}, mono={0.000000}: clock_override_set
test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_DL_TBF.request dl_tbf_nr=0 dl_slotmask=0x80 dl_tfi=0
@@ -126,3 +134,4 @@
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=43 ts=7 data_len=23 data=[40 04 00 00 00 04 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b ]
test_rlcmac_prim_down_cb(): Rx L1CTL-PDCH_DATA.request fn=47 ts=6 data_len=34 data=[00 06 00 39 01 c0 00 08 01 01 d5 71 00 00 08 29 26 24 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 00 ]
=== test_dl_tbf_ccch_assign_requests_ul_tbf_pacch end ===
+test_rlcmac_prim_down_cb(): Rx L1CTL-CFG_UL_TBF.request ul_tbf_nr=0 ul_slotmask=0x00
--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32123
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I4c98d5431a8409a6d428e96f9bfbb442bd75b24f
Gerrit-Change-Number: 32123
Gerrit-PatchSet: 2
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: merged
1
0
[M] Change in libosmo-gprs[master]: rlcmac: Release UL_TBF L1CTL resources upon free
by pespin 31 Mar '23
by pespin 31 Mar '23
31 Mar '23
pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32123 )
Change subject: rlcmac: Release UL_TBF L1CTL resources upon free
......................................................................
Patch Set 2:
(1 comment)
Patchset:
PS1:
> I guess this can be done by the modem app itself based on some timer? i.e. […]
I think that's not going to work, because at rlcmac level it is clear that upon certain conditions the MS has to go back to listening to BCCH.
If you wait too much, then the network my try to assign a DL TBF and fail.
--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32123
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I4c98d5431a8409a6d428e96f9bfbb442bd75b24f
Gerrit-Change-Number: 32123
Gerrit-PatchSet: 2
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Comment-Date: Fri, 31 Mar 2023 15:32:28 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: fixeria <vyanitskiy(a)sysmocom.de>
Comment-In-Reply-To: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: comment
1
0
[S] Change in libosmo-gprs[master]: llc: Free allocated LLMEs when freeing main context
by fixeria 31 Mar '23
by fixeria 31 Mar '23
31 Mar '23
Attention is currently required from: pespin.
fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32126 )
Change subject: llc: Free allocated LLMEs when freeing main context
......................................................................
Patch Set 1: Code-Review+2
--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32126
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: Ifb51a956d5a41f01184db4d453c64128db439f7c
Gerrit-Change-Number: 32126
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Comment-Date: Fri, 31 Mar 2023 15:32:27 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
Gerrit-MessageType: comment
1
0
[S] Change in libosmo-gprs[master]: gmm: Free allocated GMMEs when freeing main context
by fixeria 31 Mar '23
by fixeria 31 Mar '23
31 Mar '23
Attention is currently required from: pespin.
fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32125 )
Change subject: gmm: Free allocated GMMEs when freeing main context
......................................................................
Patch Set 1: Code-Review+2
--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32125
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I092b2d133467d1c2dcb8dfe5def99d49807b6273
Gerrit-Change-Number: 32125
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Comment-Date: Fri, 31 Mar 2023 15:32:08 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
Gerrit-MessageType: comment
1
0
31 Mar '23
Attention is currently required from: pespin.
fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32124 )
Change subject: gmm: Free ms_fsm when freeing gmme
......................................................................
Patch Set 1: Code-Review+2
--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32124
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: I0f2dd55bf0241a37a06e2ea438ca6ac2418eb7b8
Gerrit-Change-Number: 32124
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Comment-Date: Fri, 31 Mar 2023 15:31:55 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
Gerrit-MessageType: comment
1
0
[S] Change in libosmo-gprs[master]: gmm: Several fixes to GMMSM prim alloc functions
by fixeria 31 Mar '23
by fixeria 31 Mar '23
31 Mar '23
Attention is currently required from: pespin.
fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32101 )
Change subject: gmm: Several fixes to GMMSM prim alloc functions
......................................................................
Patch Set 3: Code-Review+2
--
To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32101
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-gprs
Gerrit-Branch: master
Gerrit-Change-Id: Ie49cb448806101a24c58a85f7073e13baccada5b
Gerrit-Change-Number: 32101
Gerrit-PatchSet: 3
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Attention: pespin <pespin(a)sysmocom.de>
Gerrit-Comment-Date: Fri, 31 Mar 2023 15:31:35 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
Gerrit-MessageType: comment
1
0