lists.osmocom.org
Sign In Sign Up
Manage this list Sign In Sign Up

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

gerrit-log

Thread Start a new thread
Download
Threads by month
  • ----- 2026 -----
  • November
  • 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
gerrit-log@lists.osmocom.org

March 2023

  • 1 participants
  • 3642 discussions
[XL] Change in libosmo-gprs[master]: gmm: Initial implementation of GPRS Attach
by pespin 24 Mar '23

24 Mar '23
pespin has submitted this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32021 ) Change subject: gmm: Initial implementation of GPRS Attach ...................................................................... gmm: Initial implementation of GPRS Attach This patch contains further work on several areas for the GMM layer, like fixes and improvements in existing primitives, initial FSM implementation, initial Tx and Rx of some GMM messages, etc. Related: OS#5501 Change-Id: I212053b3a3f27ef7d63503c3d5ef08453b2d2056 --- M include/osmocom/gprs/gmm/Makefile.am M include/osmocom/gprs/gmm/gmm.h A include/osmocom/gprs/gmm/gmm_ms_fsm.h A include/osmocom/gprs/gmm/gmm_pdu.h M include/osmocom/gprs/gmm/gmm_prim.h M include/osmocom/gprs/gmm/gmm_private.h M include/osmocom/gprs/rlcmac/rlcmac_prim.h M libosmo-gprs-gmm.pc.in M src/gmm/Makefile.am M src/gmm/gmm.c A src/gmm/gmm_ms_fsm.c A src/gmm/gmm_pdu.c M src/gmm/gmm_prim.c M src/gmm/misc.c M tests/gmm/Makefile.am M tests/gmm/gmm_prim_test.c M tests/gmm/gmm_prim_test.err M tests/gmm/gmm_prim_test.ok 18 files changed, 1,879 insertions(+), 32 deletions(-) Approvals: Jenkins Builder: Verified fixeria: Looks good to me, approved diff --git a/include/osmocom/gprs/gmm/Makefile.am b/include/osmocom/gprs/gmm/Makefile.am index c8d9baf..2adfed1 100644 --- a/include/osmocom/gprs/gmm/Makefile.am +++ b/include/osmocom/gprs/gmm/Makefile.am @@ -1,6 +1,8 @@ noinst_HEADERS = \ + gmm_ms_fsm.h \ gmm_private.h \ + gmm_pdu.h \ $(NULL) gmm_HEADERS = \ diff --git a/include/osmocom/gprs/gmm/gmm.h b/include/osmocom/gprs/gmm/gmm.h index bbd2213..49954e8 100644 --- a/include/osmocom/gprs/gmm/gmm.h +++ b/include/osmocom/gprs/gmm/gmm.h @@ -20,3 +20,5 @@ }; void osmo_gprs_gmm_set_log_cat(enum osmo_gprs_gmm_log_cat logc, int logc_num); + +void osmo_gprs_gmm_enable_gprs(bool enable_gprs); diff --git a/include/osmocom/gprs/gmm/gmm_ms_fsm.h b/include/osmocom/gprs/gmm/gmm_ms_fsm.h new file mode 100644 index 0000000..9639a9b --- /dev/null +++ b/include/osmocom/gprs/gmm/gmm_ms_fsm.h @@ -0,0 +1,51 @@ +#pragma once + +#include <osmocom/core/fsm.h> + +struct gprs_gmm_entity; + +/* 3GPP TS 24.008 § 4.1.3.1 GMM states in the MS */ +enum gprs_gmm_ms_fsm_states { + GPRS_GMM_MS_ST_NULL, /* 4.1.3.1.1.1 */ + GPRS_GMM_MS_ST_DEREGISTERED, /* 4.1.3.1.1.2 */ + GPRS_GMM_MS_ST_REGISTERED_INITIATED, /* 4.1.3.1.1.3 */ + GPRS_GMM_MS_ST_REGISTERED, /* 4.1.3.1.1.4 */ + GPRS_GMM_MS_ST_DEREGISTERED_INITIATED, /* 4.1.3.1.1.5 */ + GPRS_GMM_MS_ST_RAU_INITIATED, /* 4.1.3.1.1.6 */ + GPRS_GMM_MS_ST_SR_INITIATED, /* 4.1.3.1.1.7 (Iu only) */ + //GPRS_GMM_MS_ST_DEREGISTERED_NORMAL, /* 4.1.3.1.2.1 */ + //GPRS_GMM_MS_ST_DEREGISTERED_LIMITED, /* 4.1.3.1.2.2 */ + //GPRS_GMM_MS_ST_DEREGISTERED_ATTACH_NEEDED, /* 4.1.3.1.2.3 */ + //GPRS_GMM_MS_ST_DEREGISTERED_ATTEMTPING_ATTACH, /* 4.1.3.1.2.4 */ + //GPRS_GMM_MS_ST_DEREGISTERED_NO_IMSI, /* 4.1.3.1.2.5 */ + //GPRS_GMM_MS_ST_DEREGISTERED_NO_CELL_AVAIL, /* 4.1.3.1.2.6 */ + //GPRS_GMM_MS_ST_DEREGISTERED_PLMN_SEARCH, /* 4.1.3.1.2.7 */ + //GPRS_GMM_MS_ST_DEREGISTERED_SUSPENDED, /* 4.1.3.1.2.8 (Gb only) */ +}; + +enum gprs_gmm_ms_fsm_events { + GPRS_GMM_MS_EV_ENABLE_GPRS_MODE, + GPRS_GMM_MS_EV_DISABLE_GPRS_MODE, + GPRS_GMM_MS_EV_ATTACH_REQUESTED, + GPRS_GMM_MS_EV_ATTACH_REJECTED, + GPRS_GMM_MS_EV_ATTACH_ACCEPTED, + GPRS_GMM_MS_EV_DETACH_REQUESTED, /* poweroff or network initiated */ + GPRS_GMM_MS_EV_DETACH_ACCEPTED, + GPRS_GMM_MS_EV_SR_REQUESTED, /* (Iu only) */ + GPRS_GMM_MS_EV_SR_REJECTED, /* (Iu only) */ + GPRS_GMM_MS_EV_SR_ACCEPTED, /* (Iu only) */ + GPRS_GMM_MS_EV_RAU_REQUESTED, + GPRS_GMM_MS_EV_RAU_REJECTED, + GPRS_GMM_MS_EV_RAU_ACCEPTED, + GPRS_GMM_MS_EV_LOW_LVL_FAIL, +}; + +struct gprs_gmm_ms_fsm_ctx { + struct osmo_fsm_inst *fi; + struct gprs_gmm_entity *gmme; +}; + +int gprs_gmm_ms_fsm_init(void); +void gprs_gmm_ms_fsm_set_log_cat(int logcat); + +int gprs_gmm_ms_fsm_ctx_init(struct gprs_gmm_ms_fsm_ctx *ctx, struct gprs_gmm_entity *gmme); diff --git a/include/osmocom/gprs/gmm/gmm_pdu.h b/include/osmocom/gprs/gmm/gmm_pdu.h new file mode 100644 index 0000000..5a9faa1 --- /dev/null +++ b/include/osmocom/gprs/gmm/gmm_pdu.h @@ -0,0 +1,33 @@ +/* GMM PDUs, 3GPP TS 9.4 24.008 GPRS Mobility Management Messages */ +#pragma once + +#include <osmocom/core/msgb.h> +#include <osmocom/gsm/tlv.h> + +struct gprs_gmm_entity; + +#define GPRS_GMM_ALLOC_SIZE 2048 +#define GPRS_GMM_ALLOC_HEADROOM 256 + +static inline struct msgb *gprs_gmm_msgb_alloc_name(const char *name) +{ + return msgb_alloc_headroom(GPRS_GMM_ALLOC_SIZE, GPRS_GMM_ALLOC_HEADROOM, name); +} + +extern const struct tlv_definition gprs_gmm_att_tlvdef; +#define gprs_gmm_tlv_parse(dec, buf, len) \ + tlv_parse(dec, &gprs_gmm_att_tlvdef, buf, len, 0, 0) + +int gprs_gmm_build_attach_req(struct gprs_gmm_entity *gmme, + enum osmo_gprs_gmm_attach_type attach_type, + bool attach_with_imsi, + struct msgb *msg); + +int gprs_gmm_build_attach_compl(struct gprs_gmm_entity *gmme, struct msgb *msg); + +int gprs_gmm_build_identity_resp(struct gprs_gmm_entity *gmme, + uint8_t mi_type, + struct msgb *msg); + +int gprs_gmm_build_ciph_auth_resp(struct gprs_gmm_entity *gmme, bool imeisv_requested, + uint8_t ac_ref_nr, const uint8_t sres[4], struct msgb *msg); diff --git a/include/osmocom/gprs/gmm/gmm_prim.h b/include/osmocom/gprs/gmm/gmm_prim.h index a610986..6537075 100644 --- a/include/osmocom/gprs/gmm/gmm_prim.h +++ b/include/osmocom/gprs/gmm/gmm_prim.h @@ -13,12 +13,15 @@ #include <osmocom/core/utils.h> #include <osmocom/core/prim.h> +#include <osmocom/gsm/protocol/gsm_23_003.h> #include <osmocom/gprs/gmm/gmm.h> +struct osmo_gprs_llc_prim; + /* 3GPP TS 24.007 (index, "GMMR") */ enum osmo_gprs_gmm_prim_sap { OSMO_GPRS_GMM_SAP_GMMREG, /* 6.6 */ - OSMO_GPRS_GMM_SAP_GMMRR, /* GSM only */ + OSMO_GPRS_GMM_SAP_GMMRR, /* 9.3.2, GSM only */ OSMO_GPRS_GMM_SAP_GMMAS, /* UMTS only */ OSMO_GPRS_GMM_SAP_LLGMM, OSMO_GPRS_GMM_SAP_GMMSM, @@ -33,7 +36,7 @@ return get_value_string(osmo_gprs_gmm_prim_sap_names, val); } -/* 6.6 Registration Services for GPRS-Services */ +/* 3GPP TS 24.007 Section 6.6 Registration Services for GPRS-Services */ enum osmo_gprs_gmm_gmmreg_prim_type { OSMO_GPRS_GMM_GMMREG_ATTACH, /* Req/Cnf/Rej */ OSMO_GPRS_GMM_GMMREG_DETACH, /* Req/Cnf/Ind */ @@ -44,6 +47,16 @@ return get_value_string(osmo_gprs_gmm_gmmreg_prim_type_names, val); } +/* Attach type 10.5.5.2 */ +enum osmo_gprs_gmm_attach_type { + /* 0 is reserved */ + OSMO_GPRS_GMM_ATTACH_TYPE_GPRS = 1, + OSMO_GPRS_GMM_ATTACH_TYPE_COMBINED_OLD = 2, /* Table 10.5.135b NOTE 1 */ + OSMO_GPRS_GMM_ATTACH_TYPE_COMBINED = 3, + OSMO_GPRS_GMM_ATTACH_TYPE_EMERGENCY = 4, + /* others: reserved, interpreted as OSMO_GPRS_GMM_ATTACH_TYPE_GPRS */ +}; + /* Parameters for OSMO_GPRS_GMM_GMMREG_* prims */ struct osmo_gprs_gmm_gmmreg_prim { /* Common fields */ @@ -51,6 +64,12 @@ union { /* OSMO_GPRS_GMM_GMMREG_ATTACH | Req, 6.6.1.1 */ 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 */ } attach_req; /* OSMO_GPRS_GMM_GMMREG_ATTACH | Cnf 6.6.1.2 / Rej 6.6.1.3 */ @@ -80,10 +99,83 @@ }; }; +/* TS 24.007 Section 9.3.2 "Service primitives for GMMRR-SAP (GSM only)" + * Same as enum osmo_gprs_rlcmac_gmmrr_prim_type. + */ +enum osmo_gprs_gmm_gmmrr_prim_type { + OSMO_GPRS_GMM_GMMRR_ASSIGN, /* Req: newTLLI */ + OSMO_GPRS_GMM_GMMRR_PAGE, /* Ind: TLLI */ +}; +extern const struct value_string osmo_gprs_gmm_gmmrr_prim_type_names[]; +static inline const char *osmo_gprs_gmm_gmmrr_prim_type_name(enum osmo_gprs_gmm_gmmrr_prim_type val) +{ + return get_value_string(osmo_gprs_gmm_gmmrr_prim_type_names, val); +} + +/* Parameters for OSMO_GPRS_GMM_GMMRR_* prims + * Same as struct osmo_gprs_rlcmac_gmmrr_prim. + */ +struct osmo_gprs_gmm_gmmrr_prim { + /* Common fields (none) */ + union { + /* OSMO_GPRS_GMM_GMMRR_ASSIGN | Req */ + struct { + uint32_t new_tlli; + } assign_req; + /* OSMO_GPRS_GMM_GMMRR_PAGE | Ind */ + struct { + uint32_t tlli; + } page_ind; + }; +}; + +/* TS 24.007 Section 9.5.1 "Service primitives for GMMSM-SAP" + */ +enum osmo_gprs_gmm_gmmsm_prim_type { + OSMO_GPRS_GMM_GMMSM_ESTABLISH, /* Req, Cnf/Rej */ + OSMO_GPRS_GMM_GMMSM_RELEASE, /* Ind */ + OSMO_GPRS_GMM_GMMSM_UNITDATA, /* Req, Ind */ +}; +extern const struct value_string osmo_gprs_gmm_gmmsm_prim_type_names[]; +static inline const char *osmo_gprs_gmm_gmmsm_prim_type_name(enum osmo_gprs_gmm_gmmsm_prim_type val) +{ + return get_value_string(osmo_gprs_gmm_gmmsm_prim_type_names, val); +} + +/* Parameters for OSMO_GPRS_GMM_GMMSM_* prims + */ +struct osmo_gprs_gmm_gmmsm_prim { + /* Common fields (none) */ + union { + /* OSMO_GPRS_GMM_GMMSM_ESTABLISH | Req */ + struct { + } establish_req; + /* OSMO_GPRS_GMM_GMMSM_ESTABLISH | Cnf/Rej */ + struct { + uint8_t cause; + } establish_cnf; + /* OSMO_GPRS_GMM_GMMSM_RELEASE | Ind */ + struct { + } page_ind; + /* OSMO_GPRS_GMM_GMMSM_UNITDATA | Req */ + struct { + uint8_t *smpdu; + uint16_t smpdu_len; + } unitdata_req; + /* OSMO_GPRS_GMM_GMMSM_UNITDATA | Ind */ + struct { + uint8_t *smpdu; + uint16_t smpdu_len; + } unitdata_ind; + }; +}; + struct osmo_gprs_gmm_prim { struct osmo_prim_hdr oph; union { struct osmo_gprs_gmm_gmmreg_prim gmmreg; + struct osmo_gprs_gmm_gmmrr_prim gmmrr; + struct osmo_gprs_gmm_gmmsm_prim gmmsm; }; }; @@ -93,10 +185,22 @@ typedef int (*osmo_gprs_gmm_prim_down_cb)(struct osmo_gprs_gmm_prim *gmm_prim, void *down_user_data); void osmo_gprs_gmm_prim_set_down_cb(osmo_gprs_gmm_prim_down_cb down_cb, void *down_user_data); + +typedef int (*osmo_gprs_gmm_prim_llc_down_cb)(struct osmo_gprs_llc_prim *llc_prim, void *llc_down_user_data); +void osmo_gprs_gmm_prim_set_llc_down_cb(osmo_gprs_gmm_prim_llc_down_cb llc_down_cb, void *llc_down_user_data); + int osmo_gprs_gmm_prim_upper_down(struct osmo_gprs_gmm_prim *gmm_prim); int osmo_gprs_gmm_prim_lower_up(struct osmo_gprs_gmm_prim *gmm_prim); +int osmo_gprs_gmm_prim_llc_lower_up(struct osmo_gprs_llc_prim *llc_prim); const char *osmo_gprs_gmm_prim_name(const struct osmo_gprs_gmm_prim *gmm_prim); /* Alloc primitive for GMMREG SAP: */ struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmreg_attach_req(void); + +/* Alloc primitive for GMMRR SAP: */ +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); diff --git a/include/osmocom/gprs/gmm/gmm_private.h b/include/osmocom/gprs/gmm/gmm_private.h index d0a40a7..87b9843 100644 --- a/include/osmocom/gprs/gmm/gmm_private.h +++ b/include/osmocom/gprs/gmm/gmm_private.h @@ -10,8 +10,12 @@ #include <osmocom/core/msgb.h> #include <osmocom/core/logging.h> #include <osmocom/core/endian.h> +#include <osmocom/gsm/protocol/gsm_23_003.h> +#include <osmocom/gprs/llc/llc_prim.h> #include <osmocom/gprs/gmm/gmm.h> +#include <osmocom/gprs/gmm/gmm_prim.h> +#include <osmocom/gprs/gmm/gmm_ms_fsm.h> extern int g_gmm_log_cat[_OSMO_GPRS_GMM_LOGC_MAX]; @@ -27,6 +31,15 @@ osmo_gprs_gmm_prim_down_cb gmm_down_cb; void *gmm_down_cb_user_data; + osmo_gprs_gmm_prim_llc_down_cb gmm_llc_down_cb; + void *gmm_llc_down_cb_user_data; + + /* GPRS enabled in the system: 3GPP TS 24.008 Figure 4.1b, + * transition GMM-NULL<->GMM-DEREGISTERED */ + bool gprs_enabled; + + struct osmo_tdef *T_defs; /* timers controlled by GMM layer */ + struct llist_head gmme_list; /* list of struct gprs_gmm_entity->list */ }; @@ -35,18 +48,46 @@ /* GMM Entity: */ struct gprs_gmm_entity { struct llist_head list; /* item in (struct gprs_gmm_ctx)->gmme_list */ + + struct gprs_gmm_ms_fsm_ctx ms_fsm; + uint32_t ptmsi; + uint32_t old_ptmsi; + char imsi[OSMO_IMSI_BUF_SIZE]; + char imei[GSM23003_IMEI_NUM_DIGITS + 1]; + char imeisv[GSM23003_IMEISV_NUM_DIGITS+1]; + + uint8_t ra_upd_timer; /* TS 24.008 10.5.7.3 */ + uint8_t radio_prio; /* TS 24.008 10.5.7.2 */ + struct gprs_ra_id ra; /* TS 24.008 10.5.5.15 (decoded) */ + + uint8_t gea; /* GEA/0 = 0, GEA/1 = 1, ... */ + uint8_t kc[16]; /* max 16 * 8 = 128 bits */ }; /* gmm_prim.c: */ -struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmm_gmmreg_attach_cnf(void); int gprs_gmm_prim_call_up_cb(struct osmo_gprs_gmm_prim *gmm_prim); int gprs_gmm_prim_call_down_cb(struct osmo_gprs_gmm_prim *gmm_prim); +int gprs_gmm_prim_call_llc_down_cb(struct osmo_gprs_llc_prim *llc_prim); + +struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmreg_attach_cnf(void); +struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmreg_detach_cnf(void); + +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); /* gmm.c: */ struct gprs_gmm_entity *gprs_gmm_gmme_alloc(void); void gprs_gmm_gmme_free(struct gprs_gmm_entity *gmme); +struct gprs_gmm_entity *gprs_gmm_find_gmme_by_tlli(uint32_t tlli); +int gprs_gmm_rx(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len); +int gprs_gmm_tx_att_req(struct gprs_gmm_entity *gmme, + enum osmo_gprs_gmm_attach_type attach_type, + bool attach_with_imsi); #define LOGGMME(snme, level, fmt, args...) \ - LOGGMM(level, "GMME(%08x) " fmt, \ - 23 /*TODO: use ID */, \ + LOGGMM(level, "GMME(PTMSI-%08x) " fmt, \ + gmme->ptmsi, \ ## args) diff --git a/include/osmocom/gprs/rlcmac/rlcmac_prim.h b/include/osmocom/gprs/rlcmac/rlcmac_prim.h index 40d2d9a..cca27f6 100644 --- a/include/osmocom/gprs/rlcmac/rlcmac_prim.h +++ b/include/osmocom/gprs/rlcmac/rlcmac_prim.h @@ -61,7 +61,9 @@ }; }; -/* TS 24.007 Section 9.3.2 "Service primitives for GMMRR-SAP (GSM only)" */ +/* TS 24.007 Section 9.3.2 "Service primitives for GMMRR-SAP (GSM only)" + * Same as enum osmo_gprs_gmm_gmmrr_prim_type. + */ enum osmo_gprs_rlcmac_gmmrr_prim_type { OSMO_GPRS_RLCMAC_GMMRR_ASSIGN, /* Req: newTLLI */ OSMO_GPRS_RLCMAC_GMMRR_PAGE, /* Ind: TLLI */ @@ -73,7 +75,9 @@ return get_value_string(osmo_gprs_rlcmac_gmmrr_prim_type_names, val); } -/* Parameters for OSMO_GPRS_RLCMAC_GRR_* prims */ +/* Parameters for OSMO_GPRS_RLCMAC_GRR_* prims. + * Same as struct osmo_gprs_gmm_gmmrr_prim. + */ struct osmo_gprs_rlcmac_gmmrr_prim { /* Common fields (none) */ union { diff --git a/libosmo-gprs-gmm.pc.in b/libosmo-gprs-gmm.pc.in index d53adad..f71f1f8 100644 --- a/libosmo-gprs-gmm.pc.in +++ b/libosmo-gprs-gmm.pc.in @@ -6,7 +6,7 @@ Name: Osmocom [E]GPRS GMM (GPRS Mobility Management) Library Description: C Utility Library Version: @VERSION@ -Requires: libosmocore +Requires: libosmocore libosmo-gprs-llc Libs: -L${libdir} -losmo-gprs-gmm Libs.private: -ltalloc Cflags: -I${includedir}/ diff --git a/src/gmm/Makefile.am b/src/gmm/Makefile.am index 7120b1f..2aa8bb4 100644 --- a/src/gmm/Makefile.am +++ b/src/gmm/Makefile.am @@ -20,6 +20,8 @@ libosmo_gprs_gmm_la_SOURCES = \ gmm.c \ + gmm_ms_fsm.c \ + gmm_pdu.c \ gmm_prim.c \ misc.c \ $(NULL) @@ -31,6 +33,7 @@ $(NULL) libosmo_gprs_gmm_la_LIBADD = \ + $(top_builddir)/src/llc/libosmo-gprs-llc.la \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ -lm \ diff --git a/src/gmm/gmm.c b/src/gmm/gmm.c index afe0882..4abf3a7 100644 --- a/src/gmm/gmm.c +++ b/src/gmm/gmm.c @@ -24,24 +24,108 @@ #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/gmm/gmm.h> #include <osmocom/gprs/gmm/gmm_prim.h> #include <osmocom/gprs/gmm/gmm_private.h> +#include <osmocom/gprs/gmm/gmm_ms_fsm.h> +#include <osmocom/gprs/gmm/gmm_pdu.h> + struct gprs_gmm_ctx *g_ctx; +/* Section 11.2.2 / Table 11.3 GPRS Mobility management timers - MS side */ +#define GSM0408_T3310_SECS 15 +#define GSM0408_T3311_SECS 15 +#define GSM0408_T3316_SECS 30 +#define GSM0408_T3318_SECS 20 +#define GSM0408_T3320_SECS 15 +#define GSM0408_T3321_SECS 15 +#define GSM0408_T3330_SECS 15 +#define GSM0408_T3340_SECS 10 + +/* Section 11.2.2 / Table 11.3a GPRS Mobility management timers – MS side */ +#define GSM0408_T3302_SECS (12 * 60) +#define GSM0408_T3312_SECS (54 * 60) +#define GSM0408_T3314_SECS 44 +#define GSM0408_T3317_SECS 15 +#define GSM0408_T3319_SECS 30 +#define GSM0408_T3323_SECS GSM0408_T3312_SECS /* NOTE 6 */ +#define GSM0408_T3325_SECS 60 +#define GSM0408_T3346_SECS (15*60) + +/* TS 24.008 */ +static struct osmo_tdef T_defs_gmm[] = { + { .T=3302, .default_val=GSM0408_T3302_SECS, .desc = "" }, + { .T=3310, .default_val=GSM0408_T3310_SECS, .desc = "" }, + { .T=3311, .default_val=GSM0408_T3311_SECS, .desc = "" }, + { .T=3312, .default_val=GSM0408_T3312_SECS, .desc = "" }, + { .T=3314, .default_val=GSM0408_T3314_SECS, .desc="READY timer. Forced to STANDBY on expiry timer (s)" }, + { .T=3316, .default_val=GSM0408_T3316_SECS, .desc = "" }, + { .T=3317, .default_val=GSM0408_T3317_SECS, .desc = "" }, + { .T=3318, .default_val=GSM0408_T3318_SECS, .desc = "" }, + { .T=3319, .default_val=GSM0408_T3319_SECS, .desc = "" }, + { .T=3320, .default_val=GSM0408_T3320_SECS, .desc = "" }, + { .T=3321, .default_val=GSM0408_T3321_SECS, .desc = "" }, + { .T=3323, .default_val=GSM0408_T3323_SECS, .desc = "" }, + { .T=3324, .default_val=0 /* provided by the network */, .desc = "" }, + { .T=3325, .default_val=GSM0408_T3323_SECS, .desc = "" }, + { .T=3330, .default_val=GSM0408_T3330_SECS, .desc = "" }, + { .T=3340, .default_val=GSM0408_T3340_SECS, .desc = "" }, + { .T=3346, .default_val=GSM0408_T3346_SECS /* updated by netowrk */, .desc = "" }, + { 0 } /* empty item at the end */ +}; + int osmo_gprs_gmm_init(enum osmo_gprs_gmm_location location) { - if (g_ctx) + bool first_init = true; + int rc; + OSMO_ASSERT(location == OSMO_GPRS_GMM_LOCATION_MS || location == OSMO_GPRS_GMM_LOCATION_NETWORK) + + if (g_ctx) { + first_init = false; talloc_free(g_ctx); + } g_ctx = talloc_zero(NULL, struct gprs_gmm_ctx); g_ctx->location = location; + g_ctx->T_defs = T_defs_gmm; INIT_LLIST_HEAD(&g_ctx->gmme_list); + + osmo_tdefs_reset(g_ctx->T_defs); + + if (first_init) { + rc = gprs_gmm_ms_fsm_init(); + if (rc != 0) { + TALLOC_FREE(g_ctx); + return rc; + } + } return 0; } +/* Whether GPRS is enabled on the phone. + * See transition GMM-NULL <-> GMM-* in + * "Figure 4.1b/3GPP TS 24.008:GMM main states in the MS" */ +void osmo_gprs_gmm_enable_gprs(bool enable_gprs) +{ + struct gprs_gmm_entity *gmme; + int ev; + + if (g_ctx->gprs_enabled == enable_gprs) + return; + + g_ctx->gprs_enabled = enable_gprs; + + /* Inform all existing MS: */ + ev = enable_gprs ? GPRS_GMM_MS_EV_ENABLE_GPRS_MODE : + GPRS_GMM_MS_EV_DISABLE_GPRS_MODE; + llist_for_each_entry(gmme, &g_ctx->gmme_list, list) + osmo_fsm_inst_dispatch(gmme->ms_fsm.fi, ev, NULL); +} + struct gprs_gmm_entity *gprs_gmm_gmme_alloc(void) { struct gprs_gmm_entity *gmme; @@ -50,6 +134,11 @@ if (!gmme) return NULL; + if (gprs_gmm_ms_fsm_ctx_init(&gmme->ms_fsm, gmme) < 0) { + talloc_free(gmme); + return NULL; + } + llist_add(&gmme->list, &g_ctx->gmme_list); return gmme; @@ -64,3 +153,353 @@ llist_del(&gmme->list); talloc_free(gmme); } + +struct gprs_gmm_entity *gprs_gmm_find_gmme_by_tlli(uint32_t tlli) +{ + struct gprs_gmm_entity *gmme; + + llist_for_each_entry(gmme, &g_ctx->gmme_list, list) { + if (gmme->ptmsi == tlli || gmme->old_ptmsi == tlli) + return gmme; + } + return NULL; +} + +static 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; + + gmm_prim_tx = gprs_gmm_prim_alloc_gmmreg_attach_cnf(); + gmm_prim_tx->gmmreg.attach_cnf.accepted = accepted; + if (!accepted) + gmm_prim_tx->gmmreg.attach_cnf.rej.cause = cause; + + rc = gprs_gmm_prim_call_up_cb(gmm_prim_tx); + return rc; +} + +static int gprs_gmm_submit_gmmrr_assing_req(struct gprs_gmm_entity *gmme) +{ + struct osmo_gprs_gmm_prim *gmm_prim_tx; + int rc; + + gmm_prim_tx = gprs_gmm_prim_alloc_gmmrr_assign_req(gmme->ptmsi); + + rc = gprs_gmm_prim_call_down_cb(gmm_prim_tx); + return rc; +} + +static int gprs_gmm_submit_llgmm_assing_req(struct gprs_gmm_entity *gmme) +{ + struct osmo_gprs_llc_prim *llc_prim_tx; + int rc; + + llc_prim_tx = osmo_gprs_llc_prim_alloc_llgm_assign_req(gmme->old_ptmsi); + llc_prim_tx->llgmm.assign_req.tlli_new = gmme->ptmsi; + llc_prim_tx->llgmm.assign_req.gea = gmme->gea; + memcpy(llc_prim_tx->llgmm.assign_req.kc, gmme->kc, ARRAY_SIZE(gmme->kc)); + + rc = gprs_gmm_prim_call_llc_down_cb(llc_prim_tx); + return rc; +} + +/* Tx Identity Response, 9.2.11 */ +static int gprs_gmm_tx_id_resp(struct gprs_gmm_entity *gmme, + uint8_t mi_type) +{ + struct osmo_gprs_llc_prim *llc_prim; + int rc; + struct msgb *msg; + + LOGGMME(gmme, LOGL_INFO, "Tx GMM IDENTITY RESPONSE\n"); + + llc_prim = osmo_gprs_llc_prim_alloc_ll_unitdata_req( + gmme->ptmsi, OSMO_GPRS_LLC_SAPI_GMM, NULL, GPRS_GMM_ALLOC_SIZE); + msg = llc_prim->oph.msg; + msg->l3h = msg->tail; + rc = gprs_gmm_build_identity_resp(gmme, mi_type, msg); + if (rc < 0) { + msgb_free(msg); + return -EBADMSG; + } + llc_prim->ll.l3_pdu = msg->l3h; + llc_prim->ll.l3_pdu_len = msgb_l3len(msg); + /* TODO: + llc_prim->ll.qos_params[3]; + llc_prim->ll.radio_prio; + llc_prim->ll.apply_gea; + llc_prim->ll.apply_gia; + */ + + rc = gprs_gmm_prim_call_llc_down_cb(llc_prim); + if (rc < 0) + return rc; + return rc; +} + +/* Tx GMM Authentication and ciphering response, 9.4.10 */ +static int gprs_gmm_tx_ciph_auth_resp(struct gprs_gmm_entity *gmme, bool imeisv_requested, uint8_t ac_ref_nr, const uint8_t sres[4]) +{ + struct osmo_gprs_llc_prim *llc_prim; + int rc; + struct msgb *msg; + + LOGGMME(gmme, LOGL_INFO, "Tx GMM GMM AUTHENTICATION AND CIPHERING RESPONSE\n"); + + llc_prim = osmo_gprs_llc_prim_alloc_ll_unitdata_req( + gmme->ptmsi, OSMO_GPRS_LLC_SAPI_GMM, NULL, GPRS_GMM_ALLOC_SIZE); + msg = llc_prim->oph.msg; + msg->l3h = msg->tail; + rc = gprs_gmm_build_ciph_auth_resp(gmme, imeisv_requested, ac_ref_nr, sres, msg); + if (rc < 0) { + msgb_free(msg); + return -EBADMSG; + } + llc_prim->ll.l3_pdu = msg->l3h; + llc_prim->ll.l3_pdu_len = msgb_l3len(msg); + /* TODO: + llc_prim->ll.qos_params[3]; + llc_prim->ll.radio_prio; + llc_prim->ll.apply_gea; + llc_prim->ll.apply_gia; + */ + + rc = gprs_gmm_prim_call_llc_down_cb(llc_prim); + if (rc < 0) + return rc; + return rc; +} + +/* Tx GMM Atach Request, 9.4.1 */ +int gprs_gmm_tx_att_req(struct gprs_gmm_entity *gmme, + enum osmo_gprs_gmm_attach_type attach_type, + bool attach_with_imsi) +{ + struct osmo_gprs_llc_prim *llc_prim; + int rc; + struct msgb *msg; + + LOGGMME(gmme, LOGL_INFO, "Tx GMM ATTACH REQUEST (new P-TMSI=0x%08x)\n", gmme->ptmsi); + llc_prim = osmo_gprs_llc_prim_alloc_ll_unitdata_req( + gmme->ptmsi, OSMO_GPRS_LLC_SAPI_GMM, NULL, GPRS_GMM_ALLOC_SIZE); + msg = llc_prim->oph.msg; + msg->l3h = msg->tail; + rc = gprs_gmm_build_attach_req(gmme, + attach_type, + attach_with_imsi, + msg); + if (rc < 0) { + msgb_free(msg); + return -EBADMSG; + } + llc_prim->ll.l3_pdu = msg->l3h; + llc_prim->ll.l3_pdu_len = msgb_l3len(msg); + /* TODO: + llc_prim->ll.qos_params[3]; + llc_prim->ll.radio_prio; + llc_prim->ll.apply_gea; + llc_prim->ll.apply_gia; + */ + + rc = gprs_gmm_prim_call_llc_down_cb(llc_prim); + + return rc; +} + +/* Tx GMM Atach Complete, 9.4.3 */ +static int gprs_gmm_tx_att_compl(struct gprs_gmm_entity *gmme) +{ + struct osmo_gprs_llc_prim *llc_prim; + int rc; + struct msgb *msg; + + LOGGMME(gmme, LOGL_INFO, "Tx GMM ATTACH COMPL\n"); + + llc_prim = osmo_gprs_llc_prim_alloc_ll_unitdata_req( + gmme->ptmsi, OSMO_GPRS_LLC_SAPI_GMM, NULL, GPRS_GMM_ALLOC_SIZE); + msg = llc_prim->oph.msg; + msg->l3h = msg->tail; + rc = gprs_gmm_build_attach_compl(gmme, msg); + if (rc < 0) { + msgb_free(msg); + return -EBADMSG; + } + llc_prim->ll.l3_pdu = msg->l3h; + llc_prim->ll.l3_pdu_len = msgb_l3len(msg); + /* TODO: + llc_prim->ll.qos_params[3]; + llc_prim->ll.radio_prio; + llc_prim->ll.apply_gea; + llc_prim->ll.apply_gia; + */ + + rc = gprs_gmm_prim_call_llc_down_cb(llc_prim); + if (rc < 0) + return rc; + return rc; +} + +static int gprs_gmm_rx_att_ack(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) +{ + struct gsm48_attach_ack *aa; + struct tlv_parsed tp; + int rc; + + if (len < sizeof(*gh) + sizeof(*aa)) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM ATTACH ACCEPT with wrong size %u\n", len); + goto rejected; + } + + LOGGMME(gmme, LOGL_DEBUG, "Rx GMM ATTACH ACCEPT\n"); + aa = (struct gsm48_attach_ack *)&gh->data[0]; + + gmme->ra_upd_timer = aa->ra_upd_timer; + gmme->radio_prio = aa->radio_prio; + gsm48_parse_ra(&gmme->ra, (const uint8_t *)&aa->ra_id); + + if (len > sizeof(*gh) + sizeof(*aa)) { + rc = gprs_gmm_tlv_parse(&tp, &aa->data[0], + len - (sizeof(*gh) + sizeof(*aa))); + if (rc < 0) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM ATTACH ACCEPT: failed to parse TLVs %d\n", rc); + goto rejected; + } + + if (TLVP_PRESENT(&tp, GSM48_IE_GMM_ALLOC_PTMSI)) { + struct osmo_mobile_identity mi; + if (osmo_mobile_identity_decode(&mi, TLVP_VAL(&tp, GSM48_IE_GMM_ALLOC_PTMSI), + TLVP_LEN(&tp, GSM48_IE_GMM_ALLOC_PTMSI), false) + || mi.type != GSM_MI_TYPE_TMSI) { + LOGGMME(gmme, LOGL_ERROR, "Cannot decode P-TMSI\n"); + goto rejected; + } + gmme->old_ptmsi = gmme->ptmsi; + gmme->ptmsi = mi.tmsi; + } + } + + /* 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) + goto rejected; + + /* Submit GMMRR-ASSIGN-REQ as per TS 24.007 Annex C.1 */ + rc = gprs_gmm_submit_gmmrr_assing_req(gmme); + if (rc < 0) + goto rejected; + + rc = gprs_gmm_tx_att_compl(gmme); + if (rc < 0) + goto rejected; + + rc = osmo_fsm_inst_dispatch(gmme->ms_fsm.fi, GPRS_GMM_MS_EV_ATTACH_ACCEPTED, NULL); + + return rc; + +rejected: + return -EINVAL; /* TODO: what to do on error? */ +} + + +static int gprs_gmm_rx_att_rej(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) +{ + LOGGMME(gmme, LOGL_ERROR, "Rx GMM ATTACH REJECT not implemented!\n"); + return 0; /* TODO */ +} + +/* Rx GMM Identity Request, 9.2.10 */ +static int gprs_gmm_rx_id_req(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) +{ + /* 4.7.8.2: "An MS shall be ready to respond to an IDENTITY REQUEST message at any time." + * "Upon receipt of the IDENTITY REQUEST message the MS sends back an IDENTITY RESPONSE message. + * The IDENTITY RESPONSE message shall contain the identification parameters as requested by the network" + */ + uint8_t id_type; + + if (len < sizeof(struct gsm48_hdr) + 1) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM IDENTITY REQUEST with wrong size %u\n", len); + return -EINVAL; + } + + id_type = gh->data[0] & 0xf; + LOGGMME(gmme, LOGL_DEBUG, "Rx GMM IDENTITY REQUEST mi_type=%s\n", + gsm48_mi_type_name(id_type)); + + return gprs_gmm_tx_id_resp(gmme, id_type); +} + +/* Rx GMM Authentication and ciphering request, 9.4.9 */ +static int gprs_gmm_rx_auth_ciph_req(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) +{ + struct gsm48_auth_ciph_req *acreq; + struct tlv_parsed tp; + int rc; + bool imeisv_requested = false; + uint8_t sres[4] = {}; + + if (len < sizeof(*gh) + sizeof(*acreq)) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM AUTHENTICATION AND CIPHERING REQUEST with wrong size %u\n", len); + return -EINVAL; + } + + LOGGMME(gmme, LOGL_DEBUG, "Rx GMM AUTHENTICATION AND CIPHERING REQUEST\n"); + acreq = (struct gsm48_auth_ciph_req *)&gh->data[0]; + + if (len > sizeof(*gh) + sizeof(*acreq)) { + rc = gprs_gmm_tlv_parse(&tp, &acreq->data[0], + len - (sizeof(*gh) + sizeof(*acreq))); + if (rc < 0) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM AUTHENTICATION AND CIPHERING REQUEST: failed to parse TLVs %d\n", rc); + return -EINVAL; + } + if (TLVP_PRESENT(&tp, GSM48_IE_GMM_IMEISV)) + imeisv_requested = !!*((uint8_t *)TLVP_VAL(&tp, GSM48_IE_GMM_IMEISV)); + + } + + rc = gprs_gmm_tx_ciph_auth_resp(gmme, imeisv_requested, acreq->ac_ref_nr, sres); + if (rc < 0) + return rc; + + /* Submit LLGMM-ASSIGN-REQ as per TS 24.007 Annex C.1 */ + rc = gprs_gmm_submit_llgmm_assing_req(gmme); + return rc; +} + +/* Rx GPRS Mobility Management. */ +int gprs_gmm_rx(struct gprs_gmm_entity *gmme, struct gsm48_hdr *gh, unsigned int len) +{ + int rc = 0; + if (len < sizeof(struct gsm48_hdr)) { + LOGGMME(gmme, LOGL_ERROR, "Rx GMM message too short! len=%u\n", len); + return -EINVAL; + } + + switch (gh->msg_type) { + case GSM48_MT_GMM_ATTACH_ACK: + rc = gprs_gmm_rx_att_ack(gmme, gh, len); + break; + case GSM48_MT_GMM_ATTACH_REJ: + rc = gprs_gmm_rx_att_rej(gmme, gh, len); + break; + case GSM48_MT_GMM_ID_REQ: + rc = gprs_gmm_rx_id_req(gmme, gh, len); + break; + case GSM48_MT_GMM_AUTH_CIPH_REQ: + rc = gprs_gmm_rx_auth_ciph_req(gmme, gh, len); + break; + default: + LOGGMME(gmme, LOGL_ERROR, + "Rx GMM message not implemented! type=%u len=%u\n", + gh->msg_type, len); + rc = -EINVAL; + } + + return rc; +} diff --git a/src/gmm/gmm_ms_fsm.c b/src/gmm/gmm_ms_fsm.c new file mode 100644 index 0000000..adb73a1 --- /dev/null +++ b/src/gmm/gmm_ms_fsm.c @@ -0,0 +1,296 @@ +/* GMM states in the MS, 3GPP TS 24.008 § 4.1.3.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 <osmocom/core/tdef.h> + +#include <osmocom/gprs/gmm/gmm_ms_fsm.h> +#include <osmocom/gprs/gmm/gmm.h> +#include <osmocom/gprs/gmm/gmm_private.h> + +#define X(s) (1 << (s)) + +static const struct osmo_tdef_state_timeout gmm_ms_fsm_timeouts[32] = {}; + +#define gmm_ms_fsm_state_chg(fi, NEXT_STATE) \ + osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, gmm_ms_fsm_timeouts, g_ctx->T_defs, -1) + +static void st_gmm_ms_null(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case GPRS_GMM_MS_EV_ENABLE_GPRS_MODE: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED); + break; + case GPRS_GMM_MS_EV_DETACH_REQUESTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED); + break; + default: + OSMO_ASSERT(0); + } +} + +static void st_gmm_ms_deregistered(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + 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: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED_INITIATED); + break; + case GPRS_GMM_MS_EV_DETACH_REQUESTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED); + break; + default: + OSMO_ASSERT(0); + } +} + +static void st_gmm_ms_registered_initiated(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + 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: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); + break; + case GPRS_GMM_MS_EV_DETACH_REQUESTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED); + break; + default: + OSMO_ASSERT(0); + } +} + +static void st_gmm_ms_registered(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case GPRS_GMM_MS_EV_SR_REQUESTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); + break; + case GPRS_GMM_MS_EV_RAU_REQUESTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_RAU_INITIATED); + break; + case GPRS_GMM_MS_EV_DETACH_REQUESTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED_INITIATED); + break; + default: + OSMO_ASSERT(0); + } +} + +static void st_gmm_ms_deregistered_initiated(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case GPRS_GMM_MS_EV_DETACH_ACCEPTED: + 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_RAU_ACCEPTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); + break; + case GPRS_GMM_MS_EV_DETACH_REQUESTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED); + break; + default: + OSMO_ASSERT(0); + } +} + +static void st_gmm_ms_rau_initiated(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case GPRS_GMM_MS_EV_RAU_REJECTED: + // causes #13, #15, #25 + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); + // else + //mm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED_INITIATED); + break; + case GPRS_GMM_MS_EV_RAU_ACCEPTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); + break; + case GPRS_GMM_MS_EV_DETACH_REQUESTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED); + break; + default: + OSMO_ASSERT(0); + } +} + +static void st_gmm_ms_sr_initiated(struct osmo_fsm_inst *fi, uint32_t event, void *data) +{ + switch (event) { + case GPRS_GMM_MS_EV_SR_REJECTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); + break; + case GPRS_GMM_MS_EV_SR_ACCEPTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_REGISTERED); + break; + case GPRS_GMM_MS_EV_DETACH_REQUESTED: + gmm_ms_fsm_state_chg(fi, GPRS_GMM_MS_ST_DEREGISTERED); + break; + default: + OSMO_ASSERT(0); + } +} + +static struct osmo_fsm_state gmm_ms_fsm_states[] = { + [GPRS_GMM_MS_ST_NULL] = { + .in_event_mask = + X(GPRS_GMM_MS_EV_ENABLE_GPRS_MODE)| + X(GPRS_GMM_MS_EV_DETACH_REQUESTED), + .out_state_mask = + X(GPRS_GMM_MS_ST_DEREGISTERED), + .name = "Null", + .action = st_gmm_ms_null, + }, + [GPRS_GMM_MS_ST_DEREGISTERED] = { + .in_event_mask = + X(GPRS_GMM_MS_EV_DISABLE_GPRS_MODE) | + X(GPRS_GMM_MS_EV_ATTACH_REQUESTED) | + X(GPRS_GMM_MS_EV_DETACH_REQUESTED), + .out_state_mask = + X(GPRS_GMM_MS_ST_NULL) | + X(GPRS_GMM_MS_ST_REGISTERED_INITIATED)| + X(GPRS_GMM_MS_ST_DEREGISTERED), + .name = "Deregistered", + .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_ACCEPTED) | + X(GPRS_GMM_MS_EV_DETACH_REQUESTED), + .out_state_mask = + X(GPRS_GMM_MS_ST_DEREGISTERED) | + X(GPRS_GMM_MS_ST_REGISTERED), + .name = "RegisteredInitiated", + .action = st_gmm_ms_registered_initiated, + }, + [GPRS_GMM_MS_ST_REGISTERED] = { + .in_event_mask = + X(GPRS_GMM_MS_EV_SR_REQUESTED) | + X(GPRS_GMM_MS_EV_RAU_REQUESTED) | + X(GPRS_GMM_MS_EV_DETACH_REQUESTED) | + X(GPRS_GMM_MS_EV_DETACH_REQUESTED), + .out_state_mask = + X(GPRS_GMM_MS_ST_REGISTERED) | + X(GPRS_GMM_MS_ST_RAU_INITIATED) | + X(GPRS_GMM_MS_ST_DEREGISTERED_INITIATED) | + X(GPRS_GMM_MS_ST_DEREGISTERED), + .name = "Registered", + .action = st_gmm_ms_registered, + }, + [GPRS_GMM_MS_ST_DEREGISTERED_INITIATED] = { + .in_event_mask = + X(GPRS_GMM_MS_EV_DETACH_ACCEPTED) | + X(GPRS_GMM_MS_EV_LOW_LVL_FAIL) | + X(GPRS_GMM_MS_EV_RAU_ACCEPTED) | + X(GPRS_GMM_MS_EV_DETACH_REQUESTED), + .out_state_mask = + X(GPRS_GMM_MS_ST_REGISTERED) | + X(GPRS_GMM_MS_ST_DEREGISTERED), + .name = "DeregisteredInitiated", + .action = st_gmm_ms_sr_initiated, + }, + [GPRS_GMM_MS_ST_RAU_INITIATED] = { + .in_event_mask = + X(GPRS_GMM_MS_EV_RAU_REJECTED) | + X(GPRS_GMM_MS_EV_RAU_ACCEPTED) | + X(GPRS_GMM_MS_EV_DETACH_REQUESTED), + .out_state_mask = + X(GPRS_GMM_MS_ST_REGISTERED) | + X(GPRS_GMM_MS_ST_DEREGISTERED_INITIATED) | + X(GPRS_GMM_MS_ST_DEREGISTERED), + .name = "RAUInitidated", + .action = st_gmm_ms_rau_initiated, + }, + [GPRS_GMM_MS_ST_SR_INITIATED] = { + .in_event_mask = + X(GPRS_GMM_MS_EV_SR_REJECTED) | + X(GPRS_GMM_MS_EV_SR_ACCEPTED) | + X(GPRS_GMM_MS_EV_DETACH_REQUESTED), + .out_state_mask = + X(GPRS_GMM_MS_ST_REGISTERED) | + X(GPRS_GMM_MS_ST_DEREGISTERED), + .name = "DeregisteredInitiated", + .action = st_gmm_ms_deregistered_initiated, + }, +}; + +const struct value_string gmm_ms_fsm_event_names[] = { + { GPRS_GMM_MS_EV_ENABLE_GPRS_MODE, "ENABLE_GPRS_MODE" }, + { GPRS_GMM_MS_EV_DISABLE_GPRS_MODE, "DIOSABLE_GPRS_MODE" }, + { GPRS_GMM_MS_EV_ATTACH_REQUESTED, "ATTACH_REQUESTED" }, + { GPRS_GMM_MS_EV_ATTACH_REJECTED, "ATTACH_REJECTED" }, + { GPRS_GMM_MS_EV_ATTACH_ACCEPTED, "ATTACH_ACCEPTED" }, + { GPRS_GMM_MS_EV_DETACH_REQUESTED, "DETACH_REQUESTED" }, + { GPRS_GMM_MS_EV_DETACH_ACCEPTED, "DETACH_ACCEPTED" }, + { GPRS_GMM_MS_EV_SR_REQUESTED, "SR_REQUESTED" }, + { GPRS_GMM_MS_EV_SR_REJECTED, "SR_REJECTED" }, + { GPRS_GMM_MS_EV_SR_ACCEPTED, "SR_ACCEPTED" }, + { GPRS_GMM_MS_EV_RAU_REQUESTED, "RAU_REQUESTED" }, + { GPRS_GMM_MS_EV_RAU_REJECTED, "RAU_REJECTED" }, + { GPRS_GMM_MS_EV_RAU_ACCEPTED, "RAU_ACCEPTED" }, + { GPRS_GMM_MS_EV_LOW_LVL_FAIL, "LOW_LVL_FAIL" }, + { 0, NULL } +}; + +int gmm_ms_fsm_timer_cb(struct osmo_fsm_inst *fi) +{ + return 0; +} + +struct osmo_fsm gmm_ms_fsm = { + .name = "GMM_MS", + .states = gmm_ms_fsm_states, + .num_states = ARRAY_SIZE(gmm_ms_fsm_states), + .event_names = gmm_ms_fsm_event_names, + .log_subsys = DLGLOBAL, /* updated dynamically through gprs_gmm_ms_fsm_set_log_cat() */ + .timer_cb = gmm_ms_fsm_timer_cb, +}; + +int gprs_gmm_ms_fsm_init(void) +{ + return osmo_fsm_register(&gmm_ms_fsm); +} + +void gprs_gmm_ms_fsm_set_log_cat(int logcat) +{ + gmm_ms_fsm.log_subsys = logcat; +} + +int gprs_gmm_ms_fsm_ctx_init(struct gprs_gmm_ms_fsm_ctx *ctx, struct gprs_gmm_entity *gmme) +{ + ctx->gmme = gmme; + ctx->fi = osmo_fsm_inst_alloc(&gmm_ms_fsm, gmme, ctx, LOGL_INFO, NULL); + if (!ctx->fi) + return -ENODATA; + + /* Transition to state GMM-DEREGISTERED right away if GPRS is enabled: */ + if (g_ctx->gprs_enabled) + osmo_fsm_inst_dispatch(ctx->fi, GPRS_GMM_MS_EV_ENABLE_GPRS_MODE, NULL); + + return 0; +} diff --git a/src/gmm/gmm_pdu.c b/src/gmm/gmm_pdu.c new file mode 100644 index 0000000..141e4a5 --- /dev/null +++ b/src/gmm/gmm_pdu.c @@ -0,0 +1,330 @@ +/* GMM PDUs, 3GPP TS 9.4 24.008 GPRS Mobility 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 <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/gprs/gmm/gmm_private.h> +#include <osmocom/gprs/gmm/gmm_pdu.h> + +/* MS network capability 10.5.5.12*/ +struct gprs_gmm_ms_net_cap { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t gea1:1, + sm_cap_dedicated:1, + sm_cap_gprs:1, + ucs2_support:1, + ss_screening_ind:2, + solsa_cap:1, + rev_level_ind:1; + uint8_t pfc_feature_mode:1, + gea2:1, + gea3:1, + gea4:1, + gea5:1, + gea6:1, + gea7:1, + lcs_va_cap:1; + uint8_t ps_inter_rat_ho_geran2utran:1, + ps_inter_rat_ho_geran2eutran:1, + emm_combined_proc_cap:1, + isr_support:1, + srvcc_cap:1, + epc_cap:1, + nf_capability:1, + geran_net_sharing_cap:1; + uint8_t user_plane_integrity_protection_sup:1, + gia4:1, + gia5:1, + gia6:1, + gia7:1, + epco_ie_ind:1, + restrict_use_enhanced_cov_cap:1, + dual_conn_eutra_nr_cap:1; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t rev_level_ind:1, solsa_cap:1, ss_screening_ind:2, ucs2_support:1, sm_cap_gprs:1, sm_cap_dedicated:1, gea1:1; + uint8_t lcs_va_cap:1, gea7:1, gea6:1, gea5:1, gea4:1, gea3:1, gea2:1, pfc_feature_mode:1; + uint8_t geran_net_sharing_cap:1, nf_capability:1, epc_cap:1, srvcc_cap:1, isr_support:1, emm_combined_proc_cap:1, ps_inter_rat_ho_geran2eutran:1, ps_inter_rat_ho_geran2utran:1; + uint8_t dual_conn_eutra_nr_cap:1, restrict_use_enhanced_cov_cap:1, epco_ie_ind:1, gia7:1, gia6:1, gia5:1, gia4:1, user_plane_integrity_protection_sup:1; +#endif +} __attribute__((packed)); + +static const struct gprs_gmm_ms_net_cap ms_net_cap_def = { + .gea1 = 1, + .sm_cap_dedicated = 1, + .sm_cap_gprs = 1, + .ucs2_support = 0, + .ss_screening_ind = 1, + .solsa_cap = 0, + .rev_level_ind = 1, + .pfc_feature_mode = 1, + .gea2 = 1, + .gea3 = 1, + .gea4 = 0, + .gea5 = 0, + .gea6 = 0, + .gea7 = 0, + .lcs_va_cap = 0, + .ps_inter_rat_ho_geran2utran = 0, + .ps_inter_rat_ho_geran2eutran = 0, + .emm_combined_proc_cap = 0, + .isr_support = 0, + .srvcc_cap = 0, + .epc_cap = 0, + .nf_capability = 0, + .geran_net_sharing_cap = 0, + .user_plane_integrity_protection_sup = 0, + .gia4 = 0, + .gia5 = 0, + .gia6 = 0, + .gia7 = 0, + .epco_ie_ind = 0, + .restrict_use_enhanced_cov_cap = 0, + .dual_conn_eutra_nr_cap = 0, +}; + +/* 10.5.1.2 Ciphering Key Sequence Number */ +#define CIPH_CKSN_UNAVAIL 0x03 + +/* 10.5.5.6 DRX parameter */ +struct gprs_gmm_drx_param { +#if OSMO_IS_LITTLE_ENDIAN + uint8_t split_pg_cycle_code; + uint8_t coeff:4, + split_ccch:1, + non_drx_timer:3; +#elif OSMO_IS_BIG_ENDIAN +/* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ + uint8_t split_pg_cycle_code; + uint8_t non_drx_timer:3, split_ccch:1, coeff:4; +#endif +} __attribute__((packed)); + +static const struct gprs_gmm_drx_param drx_param_def = { + .split_pg_cycle_code = 10, + .coeff = 0, + .split_ccch = 0, + .non_drx_timer = 0, +}; + +const struct tlv_definition gprs_gmm_att_tlvdef = { + .def = { + [GSM48_IE_GMM_CIPH_CKSN] = { TLV_TYPE_SINGLE_TV, 1 }, + [GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 }, + [GSM48_IE_GMM_ALLOC_PTMSI] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_FIXED, 3 }, + [GSM48_IE_GMM_AUTH_RAND] = { TLV_TYPE_FIXED, 16 }, + [GSM48_IE_GMM_AUTH_SRES] = { TLV_TYPE_FIXED, 4 }, + [GSM48_IE_GMM_AUTH_RES_EXT] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_AUTH_FAIL_PAR] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_IMEISV] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_DRX_PARAM] = { TLV_TYPE_FIXED, 2 }, + [GSM48_IE_GMM_MS_NET_CAPA] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_PDP_CTX_STATUS] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_PS_LCS_CAPA] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_GMM_MBMS_CTX_ST] = { TLV_TYPE_TLV, 0 }, + }, +}; + +static int encode_ms_ra_acc_cap(struct gprs_gmm_entity *gmme, struct msgb *msg) +{ + int rc; + uint8_t *l; /* len */ + struct bitvec bv = { + .data = msg->tail, + .data_len = GSM_MACBLOCK_LEN, + }; + + l = msgb_put(msg, 1); /* len */ + + /* TODO: we hardcode a MS Ra Cap for now. We may want to pass it from the app at some point: */ + rc = bitvec_unhex(&bv, "171933432b37159ef98879cba28c6621e72688b198879c00"); + *l = OSMO_BYTES_FOR_BITS(bv.cur_bit); + msgb_put(msg, *l); + return rc; +} + +/* Chapter 9.4.1: Attach request */ +int gprs_gmm_build_attach_req(struct gprs_gmm_entity *gmme, + enum osmo_gprs_gmm_attach_type attach_type, + bool attach_with_imsi, + struct msgb *msg) +{ + struct gsm48_hdr *gh; + uint8_t byte, cksn; + struct osmo_mobile_identity mi; + uint8_t *l; + int rc; + struct gsm48_ra_id *raid_enc; + struct gprs_ra_id raid; + + gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + gh->proto_discr = GSM48_PDISC_MM_GPRS; + gh->msg_type = GSM48_MT_GMM_ATTACH_REQ; + + /* 10.5.5.12 MS network capability */ + msgb_lv_put(msg, sizeof(ms_net_cap_def), (const uint8_t *)&ms_net_cap_def); + + /* Attach type 10.5.5.2 */ + /* Ciphering key sequence number 10.5.1.2 */ + cksn = 0; /* Use 0 as Ciphering Key Sequence Number */ + byte = (cksn << 4) | (attach_type & 0x0f); + msgb_put_u8(msg, byte); + + /* DRX parameter 10.5.5.6 */ + memcpy(msgb_put(msg, sizeof(drx_param_def)), + &drx_param_def, + sizeof(drx_param_def)); + + /* Mobile identity 10.5.1.4 */ + /* 4.7.3.1.1: If "AttachWithIMSI" is configured, use IMSI instead: */ + if (attach_with_imsi) { + mi = (struct osmo_mobile_identity){ + .type = GSM_MI_TYPE_IMSI, + }; + OSMO_STRLCPY_ARRAY(mi.imsi, gmme->imsi); + } else { + mi = (struct osmo_mobile_identity){ + .type = GSM_MI_TYPE_TMSI, + .tmsi = gmme->ptmsi, + }; + } + l = msgb_put(msg, 1); /* len */ + rc = osmo_mobile_identity_encode_msgb(msg, &mi, false); + if (rc < 0) + return -EINVAL; + *l = rc; + + /* Old routing area identification 0.5.5.15 */ + raid = (struct gprs_ra_id){ /* TODO: fill this correctly */ + .mcc = 0, + .mnc = 0, + .mnc_3_digits = false, + .lac = 0, + .rac = 0, + }; + raid_enc = (struct gsm48_ra_id *)msgb_put(msg, sizeof(struct gsm48_ra_id)); + gsm48_encode_ra(raid_enc, &raid); + + /* MS Radio Access capability 10.5.5.12a */ + rc = encode_ms_ra_acc_cap(gmme, msg); + if (rc < 0) + return -EINVAL; + + /* TODO: optional fields */ + return 0; +} + +/* 9.4.3 Attach complete */ +int gprs_gmm_build_attach_compl(struct gprs_gmm_entity *gmme, struct msgb *msg) +{ + struct gsm48_hdr *gh; + + gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + gh->proto_discr = GSM48_PDISC_MM_GPRS; + gh->msg_type = GSM48_MT_GMM_ATTACH_COMPL; + + /* TODO: Add optional IEs */ + return 0; +} + +/* 9.2.11 Identity response */ +int gprs_gmm_build_identity_resp(struct gprs_gmm_entity *gmme, + uint8_t mi_type, + struct msgb *msg) +{ + struct gsm48_hdr *gh; + struct osmo_mobile_identity mi; + uint8_t *l; + int rc; + + gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + gh->proto_discr = GSM48_PDISC_MM_GPRS; + gh->msg_type = GSM48_MT_GMM_ID_RESP; + + /* Mobile identity 10.5.1.4 */ + switch (mi_type) { + case GSM_MI_TYPE_IMSI: + mi = (struct osmo_mobile_identity){ + .type = GSM_MI_TYPE_IMSI, + }; + OSMO_STRLCPY_ARRAY(mi.imsi, gmme->imsi); + break; + case GSM_MI_TYPE_TMSI: + mi = (struct osmo_mobile_identity){ + .type = GSM_MI_TYPE_TMSI, + .tmsi = gmme->ptmsi, + }; + break; + case GSM_MI_TYPE_IMEI: + mi = (struct osmo_mobile_identity){ + .type = GSM_MI_TYPE_IMEI, + }; + OSMO_STRLCPY_ARRAY(mi.imei, gmme->imei); + break; + case GSM_MI_TYPE_IMEISV: + mi = (struct osmo_mobile_identity){ + .type = GSM_MI_TYPE_IMEISV, + }; + OSMO_STRLCPY_ARRAY(mi.imeisv, gmme->imeisv); + break; + default: + LOGGMME(gmme, LOGL_ERROR, "Tx GMM IDENTITY RESPONSE: mi_type=%s not supported!\n", + gsm48_mi_type_name(mi_type)); + return -EINVAL; + } + l = msgb_put(msg, 1); /* len */ + rc = osmo_mobile_identity_encode_msgb(msg, &mi, false); + if (rc < 0) + return -EINVAL; + *l = rc; + + /* TODO: Optional IEs */ + return 0; +} + +/* Tx GMM Authentication and ciphering response, 9.4.10 */ +int gprs_gmm_build_ciph_auth_resp(struct gprs_gmm_entity *gmme, bool imeisv_requested, + uint8_t ac_ref_nr, const uint8_t sres[4], struct msgb *msg) +{ + struct gsm48_hdr *gh; + struct gsm48_auth_ciph_resp *acr; + int rc = 0; + + gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh)); + gh->proto_discr = GSM48_PDISC_MM_GPRS; + gh->msg_type = GSM48_MT_GMM_AUTH_CIPH_RESP; + + acr = (struct gsm48_auth_ciph_resp *) msgb_put(msg, sizeof(*acr)); + acr->ac_ref_nr = ac_ref_nr; + + if (imeisv_requested) { + (void)imeisv_requested; + /* TODO: IMEISV IE */ + } + + /* TODO: Optional IEs, eg Authentication parameter */ + return rc; +} diff --git a/src/gmm/gmm_prim.c b/src/gmm/gmm_prim.c index 87fb6e6..c18d9d5 100644 --- a/src/gmm/gmm_prim.c +++ b/src/gmm/gmm_prim.c @@ -29,6 +29,7 @@ #include <osmocom/gprs/gmm/gmm.h> #include <osmocom/gprs/gmm/gmm_prim.h> #include <osmocom/gprs/gmm/gmm_private.h> +#include <osmocom/gprs/gmm/gmm_pdu.h> #define GMM_MSGB_HEADROOM 0 @@ -51,6 +52,18 @@ { 0, NULL } }; +const struct value_string osmo_gprs_gmm_gmmrr_prim_type_names[] = { + { OSMO_GPRS_GMM_GMMRR_ASSIGN, "ASSIGN" }, + { OSMO_GPRS_GMM_GMMRR_PAGE, "PAGE" }, + { 0, NULL } +}; + +const struct value_string osmo_gprs_gmm_gmmsm_prim_type_names[] = { + { OSMO_GPRS_GMM_GMMSM_ESTABLISH, "ESTABLISH" }, + { OSMO_GPRS_GMM_GMMSM_RELEASE, "RELEASE" }, + { OSMO_GPRS_GMM_GMMSM_UNITDATA, "UNITDATA" }, + { 0, NULL } +}; const char *osmo_gprs_gmm_prim_name(const struct osmo_gprs_gmm_prim *gmm_prim) { @@ -63,6 +76,12 @@ case OSMO_GPRS_GMM_SAP_GMMREG: type = osmo_gprs_gmm_gmmreg_prim_type_name(gmm_prim->oph.primitive); break; + case OSMO_GPRS_GMM_SAP_GMMRR: + type = osmo_gprs_gmm_gmmrr_prim_type_name(gmm_prim->oph.primitive); + break; + case OSMO_GPRS_GMM_SAP_GMMSM: + type = osmo_gprs_gmm_gmmsm_prim_type_name(gmm_prim->oph.primitive); + break; default: type = "unsupported-gmm-sap"; } @@ -73,13 +92,19 @@ static int gmm_up_cb_dummy(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data) { - LOGGMM(LOGL_INFO, "gmm_up_cb_dummy(%s)\n", osmo_gprs_gmm_prim_name(gmm_prim)); + LOGGMM(LOGL_INFO, "%s(%s)\n", __func__, osmo_gprs_gmm_prim_name(gmm_prim)); return 0; } static int gmm_down_cb_dummy(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data) { - LOGGMM(LOGL_INFO, "gmm_down_cb_dummy(%s)\n", osmo_gprs_gmm_prim_name(gmm_prim)); + LOGGMM(LOGL_INFO, "%s(%s)\n", __func__, osmo_gprs_gmm_prim_name(gmm_prim)); + return 0; +} + +static int gmm_llc_down_cb_dummy(struct osmo_gprs_llc_prim *llc_prim, void *user_data) +{ + LOGGMM(LOGL_INFO, "%s(%s)\n", __func__, osmo_gprs_llc_prim_name(llc_prim)); return 0; } @@ -97,6 +122,13 @@ g_ctx->gmm_down_cb_user_data = down_user_data; } +/* Set callback used by GMM layer to push primitives to LLC lower layer in protocol stack */ +void osmo_gprs_gmm_prim_set_llc_down_cb(osmo_gprs_gmm_prim_llc_down_cb llc_down_cb, void *llc_down_user_data) +{ + g_ctx->gmm_llc_down_cb = llc_down_cb; + g_ctx->gmm_llc_down_cb_user_data = llc_down_user_data; +} + /******************************** * Primitive allocation: ********************************/ @@ -127,7 +159,7 @@ return gmm_prim; } -/*** SN ***/ +/*** GMMREG ***/ static inline struct osmo_gprs_gmm_prim *gmm_prim_gmmreg_alloc(enum osmo_gprs_gmm_gmmreg_prim_type type, enum osmo_prim_operation operation, @@ -157,7 +189,7 @@ /* TODO: 6.6.1.3 GMMREG-ATTACH.rej */ /* TS 24.007 6.6.1.4 GMMREG-DETACH.request */ -struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_detach_req(void) +struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmreg_detach_req(void) { struct osmo_gprs_gmm_prim *gmm_prim; gmm_prim = gmm_prim_gmmreg_alloc(OSMO_GPRS_GMM_GMMREG_DETACH, PRIM_OP_REQUEST, 0); @@ -180,6 +212,87 @@ return gmm_prim; } +/*** GMMRR ***/ + +static inline struct osmo_gprs_gmm_prim *gmm_prim_gmmrr_alloc(enum osmo_gprs_gmm_gmmrr_prim_type type, + enum osmo_prim_operation operation, + unsigned int extra_size) +{ + return gprs_gmm_prim_alloc(OSMO_GPRS_GMM_SAP_GMMRR, type, operation, extra_size); +} + +/* 3GPP TS 24.007 9.3.2.1 GMMRR-ASSIGN-REQ:*/ +struct osmo_gprs_gmm_prim *gprs_gmm_prim_alloc_gmmrr_assign_req(uint32_t new_tlli) +{ + struct osmo_gprs_gmm_prim *gmm_prim; + gmm_prim = gmm_prim_gmmrr_alloc(OSMO_GPRS_GMM_GMMRR_ASSIGN, PRIM_OP_REQUEST, 0); + gmm_prim->gmmrr.assign_req.new_tlli = new_tlli; + return gmm_prim; +} + +/* 3GPP TS 24.007 9.3.2.2 GMMRR-PAGE-IND:*/ +struct osmo_gprs_gmm_prim *osmo_gprs_gmm_prim_alloc_gmmrr_page_ind(uint32_t tlli) +{ + struct osmo_gprs_gmm_prim *gmm_prim; + gmm_prim = gmm_prim_gmmrr_alloc(OSMO_GPRS_GMM_GMMRR_PAGE, PRIM_OP_INDICATION, 0); + gmm_prim->gmmrr.page_ind.tlli = tlli; + return gmm_prim; +} + +/*** GMMSM ***/ + +static inline struct osmo_gprs_gmm_prim *gmm_prim_gmmsm_alloc(enum osmo_gprs_gmm_gmmrr_prim_type type, + enum osmo_prim_operation operation, + unsigned int extra_size) +{ + return gprs_gmm_prim_alloc(OSMO_GPRS_GMM_SAP_GMMSM, type, operation, extra_size); +} + +/* 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 *gmm_prim; + gmm_prim = gmm_prim_gmmrr_alloc(OSMO_GPRS_GMM_GMMSM_ESTABLISH, PRIM_OP_REQUEST, 0); + 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 *gmm_prim; + gmm_prim = gmm_prim_gmmrr_alloc(OSMO_GPRS_GMM_GMMSM_ESTABLISH, PRIM_OP_CONFIRM, 0); + gmm_prim->gmmsm.establish_cnf.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_gmmrr_release_ind(void) +{ + struct osmo_gprs_gmm_prim *gmm_prim; + gmm_prim = gmm_prim_gmmrr_alloc(OSMO_GPRS_GMM_GMMSM_RELEASE, PRIM_OP_INDICATION, 0); + 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) +{ + struct osmo_gprs_gmm_prim *gmm_prim; + gmm_prim = gmm_prim_gmmrr_alloc(OSMO_GPRS_GMM_GMMSM_UNITDATA, PRIM_OP_REQUEST, 0); + 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) +{ + struct osmo_gprs_gmm_prim *gmm_prim; + gmm_prim = gmm_prim_gmmrr_alloc(OSMO_GPRS_GMM_GMMSM_UNITDATA, PRIM_OP_INDICATION, 0); + gmm_prim->gmmsm.unitdata_ind.smpdu = smpdu; + gmm_prim->gmmsm.unitdata_ind.smpdu_len = smpdu_len; + return gmm_prim; +} + static int gprs_gmm_prim_handle_unsupported(struct osmo_gprs_gmm_prim *gmm_prim) { LOGGMM(LOGL_ERROR, "Unsupported gmm_prim! %s\n", osmo_gprs_gmm_prim_name(gmm_prim)); @@ -187,6 +300,13 @@ return -ENOTSUP; } +static int gprs_gmm_prim_handle_llc_unsupported(struct osmo_gprs_llc_prim *llc_prim) +{ + LOGGMM(LOGL_ERROR, "Unsupported llc_prim! %s\n", osmo_gprs_llc_prim_name(llc_prim)); + msgb_free(llc_prim->oph.msg); + return -ENOTSUP; +} + /******************************** * Handling from/to upper layers: ********************************/ @@ -206,10 +326,30 @@ static int gprs_gmm_prim_handle_gmmreg_attach_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->gmmreg.attach_req.ptmsi; + if (gmm_prim->gmmreg.attach_req.imsi[0] != '\0') + OSMO_STRLCPY_ARRAY(gmme->imsi, gmm_prim->gmmreg.attach_req.imsi); + if (gmm_prim->gmmreg.attach_req.imei[0] != '\0') + OSMO_STRLCPY_ARRAY(gmme->imei, gmm_prim->gmmreg.attach_req.imei); + if (gmm_prim->gmmreg.attach_req.imeisv[0] != '\0') + OSMO_STRLCPY_ARRAY(gmme->imeisv, gmm_prim->gmmreg.attach_req.imeisv); - msgb_free(gmm_prim->oph.msg); + 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); + return rc; } @@ -220,20 +360,12 @@ rc = gprs_gmm_prim_handle_unsupported(gmm_prim); - msgb_free(gmm_prim->oph.msg); return rc; } -/* GMM higher layers push GMM primitive down to GMM layer: */ -int osmo_gprs_gmm_prim_upper_down(struct osmo_gprs_gmm_prim *gmm_prim) +static int gprs_gmm_prim_handle_gmmreg(struct osmo_gprs_gmm_prim *gmm_prim) { int rc; - OSMO_ASSERT(g_ctx); - - LOGGMM(LOGL_INFO, "Rx from upper layers: %s\n", osmo_gprs_gmm_prim_name(gmm_prim)); - - if (gmm_prim->oph.sap != OSMO_GPRS_GMM_SAP_GMMREG) - return gprs_gmm_prim_handle_unsupported(gmm_prim); switch (OSMO_PRIM_HDR(&gmm_prim->oph)) { case OSMO_PRIM(OSMO_GPRS_GMM_GMMREG_ATTACH, PRIM_OP_REQUEST): @@ -248,6 +380,72 @@ return rc; } +/* TS 24.007 9.5.1.1 GMMSM-Establish.request:*/ +static int gprs_gmm_prim_handle_gmmsm_establish_req(struct osmo_gprs_gmm_prim *gmm_prim) +{ + int rc; + + rc = gprs_gmm_prim_handle_unsupported(gmm_prim); + + return rc; +} + +/* TS 24.007 9.5.1.5 GMMSM-Unitdata.request:*/ +static int gprs_gmm_prim_handle_gmmsm_unitdata_req(struct osmo_gprs_gmm_prim *gmm_prim) +{ + int rc; + + rc = gprs_gmm_prim_handle_unsupported(gmm_prim); + + return rc; +} + +static int gprs_gmm_prim_handle_gmmsm(struct osmo_gprs_gmm_prim *gmm_prim) +{ + int rc; + + switch (OSMO_PRIM_HDR(&gmm_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_ESTABLISH, PRIM_OP_REQUEST): + rc = gprs_gmm_prim_handle_gmmsm_establish_req(gmm_prim); + break; + case OSMO_PRIM(OSMO_GPRS_GMM_GMMSM_UNITDATA, PRIM_OP_REQUEST): + rc = gprs_gmm_prim_handle_gmmsm_unitdata_req(gmm_prim); + break; + default: + rc = gprs_gmm_prim_handle_unsupported(gmm_prim); + rc = 1; + } + return rc; +} + +/* GMM higher layers push GMM primitive down to GMM layer: */ +int osmo_gprs_gmm_prim_upper_down(struct osmo_gprs_gmm_prim *gmm_prim) +{ + int rc; + + LOGGMM(LOGL_INFO, "Rx from upper layers: %s\n", osmo_gprs_gmm_prim_name(gmm_prim)); + + + switch (gmm_prim->oph.sap) { + case OSMO_GPRS_GMM_SAP_GMMREG: + rc = gprs_gmm_prim_handle_gmmreg(gmm_prim); + break; + case OSMO_GPRS_GMM_SAP_GMMSM: + rc = gprs_gmm_prim_handle_gmmsm(gmm_prim); + break; + default: + rc = gprs_gmm_prim_handle_unsupported(gmm_prim); + rc = 1; + } + + /* Special return value '1' means: do not free */ + if (rc != 1) + msgb_free(gmm_prim->oph.msg); + else + rc = 0; + return rc; +} + /******************************** * Handling from/to lower layers: ********************************/ @@ -263,6 +461,21 @@ return rc; } +static int gprs_gmm_prim_handle_gmmrr(struct osmo_gprs_gmm_prim *gmm_prim) +{ + int rc = 0; + switch (OSMO_PRIM_HDR(&gmm_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_GMM_GMMRR_PAGE, PRIM_OP_INDICATION): + rc = gprs_gmm_prim_handle_unsupported(gmm_prim); + rc = 1; + break; + default: + rc = gprs_gmm_prim_handle_unsupported(gmm_prim); + rc = 1; + } + return rc; +} + /* GMM lower layers (LLC) push GMM primitive up to GMM layer: */ int osmo_gprs_gmm_prim_lower_up(struct osmo_gprs_gmm_prim *gmm_prim) { @@ -274,9 +487,8 @@ LOGGMM(LOGL_INFO, "Rx from lower layers: %s\n", osmo_gprs_gmm_prim_name(gmm_prim)); switch (gmm_prim->oph.sap) { - case OSMO_GPRS_GMM_SAP_LLGMM: - rc = gprs_gmm_prim_handle_unsupported(gmm_prim); - rc = 1; + case OSMO_GPRS_GMM_SAP_GMMRR: + rc = gprs_gmm_prim_handle_gmmrr(gmm_prim); break; default: rc = gprs_gmm_prim_handle_unsupported(gmm_prim); @@ -290,3 +502,114 @@ rc = 0; return rc; } + +int gprs_gmm_prim_call_llc_down_cb(struct osmo_gprs_llc_prim *llc_prim) +{ + int rc; + if (g_ctx->gmm_llc_down_cb) + rc = g_ctx->gmm_llc_down_cb(llc_prim, g_ctx->gmm_llc_down_cb_user_data); + else + rc = gmm_llc_down_cb_dummy(llc_prim, g_ctx->gmm_llc_down_cb_user_data); + /* Special return value '1' means: do not free */ + if (rc != 1) + msgb_free(llc_prim->oph.msg); + else + rc = 0; + return rc; +} + +static int gprs_gmm_prim_handle_llgmm(struct osmo_gprs_llc_prim *llc_prim) +{ + int rc = 0; + switch (OSMO_PRIM_HDR(&llc_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_LLC_LLGMM_PAGE, PRIM_OP_INDICATION): + rc = gprs_gmm_prim_handle_llc_unsupported(llc_prim); + rc = 1; + break; + case OSMO_PRIM(OSMO_GPRS_LLC_LLGMM_PSHO, PRIM_OP_INDICATION): + rc = gprs_gmm_prim_handle_llc_unsupported(llc_prim); + rc = 1; + break; + case OSMO_PRIM(OSMO_GPRS_LLC_LLGMM_PSHO, PRIM_OP_CONFIRM): + rc = gprs_gmm_prim_handle_llc_unsupported(llc_prim); + rc = 1; + break; + } + return rc; +} + +static int gprs_gmm_prim_handle_ll_unitdata_ind(struct osmo_gprs_llc_prim *llc_prim) +{ + struct gprs_gmm_entity *gmme; + int rc = 0; + gmme = gprs_gmm_find_gmme_by_tlli(llc_prim->ll.tlli); + if (!gmme) { + LOGGMM(LOGL_NOTICE, "Rx %s: Unknown TLLI 0x%08x\n", + osmo_gprs_llc_prim_name(llc_prim), llc_prim->ll.tlli); + return -ENOENT; + } + rc = gprs_gmm_rx(gmme, + (struct gsm48_hdr *)llc_prim->ll.l3_pdu, + llc_prim->ll.l3_pdu_len); + + return rc; +} + +static int gprs_gmm_prim_handle_ll(struct osmo_gprs_llc_prim *llc_prim) +{ + int rc; + + switch (OSMO_PRIM_HDR(&llc_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_LLC_LL_RESET, PRIM_OP_INDICATION): + case OSMO_PRIM(OSMO_GPRS_LLC_LL_ESTABLISH, PRIM_OP_INDICATION): + case OSMO_PRIM(OSMO_GPRS_LLC_LL_ESTABLISH, PRIM_OP_CONFIRM): + case OSMO_PRIM(OSMO_GPRS_LLC_LL_RELEASE, PRIM_OP_INDICATION): + case OSMO_PRIM(OSMO_GPRS_LLC_LL_RELEASE, PRIM_OP_CONFIRM): + case OSMO_PRIM(OSMO_GPRS_LLC_LL_DATA, PRIM_OP_INDICATION): + case OSMO_PRIM(OSMO_GPRS_LLC_LL_DATA, PRIM_OP_CONFIRM): + rc = gprs_gmm_prim_handle_llc_unsupported(llc_prim); + rc = 1; + break; + case OSMO_PRIM(OSMO_GPRS_LLC_LL_UNITDATA, PRIM_OP_INDICATION): + rc = gprs_gmm_prim_handle_ll_unitdata_ind(llc_prim); + break; + case OSMO_PRIM(OSMO_GPRS_LLC_LL_UNITDATA, PRIM_OP_CONFIRM): + case OSMO_PRIM(OSMO_GPRS_LLC_LL_STATUS, PRIM_OP_INDICATION): + default: + rc = gprs_gmm_prim_handle_llc_unsupported(llc_prim); + rc = 1; + break; + } + + return rc; +} + +/* GMM lower layers (LLC) push GMM primitive up to GMM layer: */ +int osmo_gprs_gmm_prim_llc_lower_up(struct osmo_gprs_llc_prim *llc_prim) +{ + OSMO_ASSERT(g_ctx); + OSMO_ASSERT(llc_prim); + struct msgb *msg = llc_prim->oph.msg; + int rc; + + 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: + rc = gprs_gmm_prim_handle_llgmm(llc_prim); + break; + case OSMO_GPRS_LLC_SAP_LL: + rc = gprs_gmm_prim_handle_ll(llc_prim); + break; + default: + rc = gprs_gmm_prim_handle_llc_unsupported(llc_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/src/gmm/misc.c b/src/gmm/misc.c index ac141ee..dec0c78 100644 --- a/src/gmm/misc.c +++ b/src/gmm/misc.c @@ -21,6 +21,7 @@ #include <osmocom/core/logging.h> #include <osmocom/core/utils.h> #include <osmocom/gprs/gmm/gmm.h> +#include <osmocom/gprs/gmm/gmm_ms_fsm.h> int g_gmm_log_cat[_OSMO_GPRS_GMM_LOGC_MAX] = { [0 ... _OSMO_GPRS_GMM_LOGC_MAX - 1] = DLGLOBAL }; @@ -28,4 +29,6 @@ { OSMO_ASSERT(logc < _OSMO_GPRS_GMM_LOGC_MAX); g_gmm_log_cat[logc] = logc_num; + + gprs_gmm_ms_fsm_set_log_cat(logc_num); } diff --git a/tests/gmm/Makefile.am b/tests/gmm/Makefile.am index 3885fb5..fb3396d 100644 --- a/tests/gmm/Makefile.am +++ b/tests/gmm/Makefile.am @@ -21,9 +21,11 @@ gmm_prim_test.ok \ $(NULL) +# libosmo-gprs-llc.a is used below to access non-exported private symbols used in the test: gmm_prim_test_SOURCES = gmm_prim_test.c gmm_prim_test_LDADD = \ $(top_builddir)/src/gmm/libosmo-gprs-gmm.la \ + $(top_builddir)/src/llc/.libs/libosmo-gprs-llc.a \ $(LIBOSMOCORE_LIBS) \ $(LIBOSMOGSM_LIBS) \ $(NULL) diff --git a/tests/gmm/gmm_prim_test.c b/tests/gmm/gmm_prim_test.c index c282d58..fdc50b7 100644 --- a/tests/gmm/gmm_prim_test.c +++ b/tests/gmm/gmm_prim_test.c @@ -26,18 +26,130 @@ #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/llc/llc_prim.h> +#include <osmocom/gprs/llc/llc_private.h> #include <osmocom/gprs/gmm/gmm.h> #include <osmocom/gprs/gmm/gmm_prim.h> +#include <osmocom/gprs/gmm/gmm_pdu.h> static void *tall_ctx = NULL; +/* +GSM A-I/F DTAP - Identity Request + Protocol Discriminator: GPRS mobility management messages (8) + .... 1000 = Protocol discriminator: GPRS mobility management messages (0x8) + 0000 .... = Skip Indicator: No indication of selected PLMN (0) + DTAP GPRS Mobility Management Message Type: Identity Request (0x15) + Identity Type 2 + .... 0... = Spare bit(s): 0 + .... .010 = Type of identity: IMEI (2) + Force to Standby + 0... .... = Spare bit(s): 0 + .000 .... = Force to standby: Force to standby not indicated (0) +*/ +static uint8_t pdu_gmm_identity_req[] = { 0x08, 0x15, 0x02 }; + +/* +Frame 101: 127 bytes on wire (1016 bits), 127 bytes captured (1016 bits) on interface lo, id 0 +Ethernet II, Src: 00:00:00_00:00:00 (00:00:00:00:00:00), Dst: 00:00:00_00:00:00 (00:00:00:00:00:00) +Internet Protocol Version 4, Src: 192.168.1.140, Dst: 192.168.1.140 +User Datagram Protocol, Src Port: 23000, Dst Port: 23010 +GPRS Network Service, PDU type: NS_UNITDATA, BVCI 1800 +Base Station Subsystem GPRS Protocol +MS-SGSN LLC (Mobile Station - Serving GPRS Support Node Logical Link Control) SAPI: GPRS Mobility Management +GSM A-I/F DTAP - Authentication and Ciphering Req + Protocol Discriminator: GPRS mobility management messages (8) + .... 1000 = Protocol discriminator: GPRS mobility management messages (0x8) + 0000 .... = Skip Indicator: No indication of selected PLMN (0) + DTAP GPRS Mobility Management Message Type: Authentication and Ciphering Req (0x12) + Ciphering Algorithm + .... 0... = Spare bit(s): 0 + .... .000 = Type of ciphering algorithm: ciphering not used (0) + IMEISV Request + 0... .... = Spare bit(s): 0 + .001 .... = IMEISV request: IMEISV requested (1) + Force to Standby + .... 0... = Spare bit(s): 0 + .... .000 = Force to standby: Force to standby not indicated (0) + A&C Reference Number + 0010 .... = A&C reference number: 2 + Authentication Parameter RAND + Element ID: 0x21 + RAND value: e2a6f3f8bb9ea701e0ce4f3364a99175 + Ciphering Key Sequence Number + 1000 .... = Element ID: 0x8- + .... 0... = Spare bit(s): 0 + .... .000 = key sequence: Ciphering key sequence number (0) +*/ +static uint8_t pdu_gmm_auth_ciph_req[] = { + 0x08, 0x12, 0x10, 0x20, 0x21, 0xe2, 0xa6, 0xf3, 0xf8, 0xbb, 0x9e, 0xa7, 0x01, 0xe0, 0xce, 0x4f, + 0x33, 0x64, 0xa9, 0x91, 0x75, 0x80 +}; + +/* +GSM A-I/F DTAP - Attach Accept + Protocol Discriminator: GPRS mobility management messages (8) + .... 1000 = Protocol discriminator: GPRS mobility management messages (0x8) + 0000 .... = Skip Indicator: No indication of selected PLMN (0) + DTAP GPRS Mobility Management Message Type: Attach Accept (0x02) + Attach Result + .... 0... = Follow-on proceed: False + .... .001 = Result of attach: GPRS only attached (1) + Force to Standby + 0... .... = Spare bit(s): 0 + .000 .... = Force to standby: Force to standby not indicated (0) + GPRS Timer + GPRS Timer: 10 min + 001. .... = Unit: value is incremented in multiples of 1 minute (1) + ...0 1010 = Timer value: 10 + Radio Priority 2 - Radio priority for TOM8 + .100 .... = Radio Priority (TOM8): priority level 4 (lowest) (4) + Radio Priority - Radio priority for SMS + .... .100 = Radio Priority (PDP or SMS): priority level 4 (lowest) (4) + Routing Area Identification - RAI: 234-70-5-0 + Routing area identification: 234-70-5-0 + Mobile Country Code (MCC): United Kingdom (234) + Mobile Network Code (MNC): AMSUK Limited (70) + Location Area Code (LAC): 0x0005 (5) + Routing Area Code (RAC): 0x00 (0) + GPRS Timer - Negotiated Ready Timer + Element ID: 0x17 + GPRS Timer: 44 sec + 000. .... = Unit: value is incremented in multiples of 2 seconds (0) + ...1 0110 = Timer value: 22 + Mobile Identity - Allocated P-TMSI - TMSI/P-TMSI (0xea711b41) + Element ID: 0x18 + Length: 5 + 1111 .... = Unused: 0xf + .... 0... = Odd/even indication: Even number of identity digits + .... .100 = Mobile Identity Type: TMSI/P-TMSI/M-TMSI (4) + TMSI/P-TMSI/M-TMSI/5G-TMSI: 3933281089 (0xea711b41) +*/ +static uint8_t pdu_gmm_att_acc[] = { +0x08, 0x02, 0x01, 0x2a, 0x44, 0x32, 0xf4, 0x07, 0x00, 0x05, 0x00, 0x17, 0x16, 0x18, 0x05, 0xf4, +0xea, 0x71, 0x1b, 0x41 +}; + int test_gmm_prim_up_cb(struct osmo_gprs_gmm_prim *gmm_prim, void *user_data) { const char *pdu_name = osmo_gprs_gmm_prim_name(gmm_prim); switch (gmm_prim->oph.sap) { + case OSMO_GPRS_GMM_SAP_GMMREG: + switch (OSMO_PRIM_HDR(&gmm_prim->oph)) { + case OSMO_PRIM(OSMO_GPRS_GMM_GMMREG_ATTACH, PRIM_OP_CONFIRM): + printf("%s(): Rx %s accepted=%u rej_cause=%u\n", __func__, pdu_name, + gmm_prim->gmmreg.attach_cnf.accepted, + gmm_prim->gmmreg.attach_cnf.rej.cause); + 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); @@ -50,6 +162,31 @@ const char *pdu_name = osmo_gprs_gmm_prim_name(gmm_prim); switch (gmm_prim->oph.sap) { + case OSMO_GPRS_GMM_SAP_GMMRR: + OSMO_ASSERT(OSMO_PRIM_HDR(&gmm_prim->oph) == + OSMO_PRIM(OSMO_GPRS_GMM_GMMRR_ASSIGN, PRIM_OP_REQUEST)); + printf("%s(): Rx %s new_tlli=0x%08x\n", __func__, pdu_name, gmm_prim->gmmrr.assign_req.new_tlli); + break; + default: + printf("%s(): Unexpected Rx %s\n", __func__, pdu_name); + OSMO_ASSERT(0); + } + return 0; +} + +int test_gmm_prim_llc_down_cb(struct osmo_gprs_llc_prim *llc_prim, void *user_data) +{ + const char *pdu_name = osmo_gprs_llc_prim_name(llc_prim); + + switch (llc_prim->oph.sap) { + case OSMO_GPRS_LLC_SAP_LLGM: + printf("%s(): Rx %s TLLI=0x%08x\n", __func__, pdu_name, llc_prim->llgmm.tlli); + break; + case OSMO_GPRS_LLC_SAP_LL: + printf("%s(): Rx %s TLLI=0x%08x SAPI=%s l3=[%s]\n", __func__, pdu_name, + llc_prim->ll.tlli, osmo_gprs_llc_sapi_name(llc_prim->ll.sapi), + osmo_hexdump(llc_prim->ll.l3_pdu, llc_prim->ll.l3_pdu_len)); + break; default: printf("%s(): Unexpected Rx %s\n", __func__, pdu_name); OSMO_ASSERT(0); @@ -59,21 +196,57 @@ static void test_gmm_prim_ms(void) { - //struct osmo_gprs_gmm_prim *gmm_prim; + 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"; 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); - //gmm_prim = osmo_gprs_gmm_prim_alloc_gmmreg_attach_req(); - //OSMO_ASSERT(gmm_prim); - //rc = osmo_gprs_gmm_prim_upper_down(gmm_prim); - //OSMO_ASSERT(rc == 0); + /* MS sends GMM Attach Req */ + gmm_prim = osmo_gprs_gmm_prim_alloc_gmmreg_attach_req(); + gmm_prim->gmmreg.attach_req.attach_type = OSMO_GPRS_GMM_ATTACH_TYPE_GPRS; + gmm_prim->gmmreg.attach_req.ptmsi = ptmsi; + OSMO_STRLCPY_ARRAY(gmm_prim->gmmreg.attach_req.imsi, imsi); + OSMO_STRLCPY_ARRAY(gmm_prim->gmmreg.attach_req.imei, imei); + OSMO_STRLCPY_ARRAY(gmm_prim->gmmreg.attach_req.imeisv, imeisv); + + OSMO_ASSERT(gmm_prim); + rc = osmo_gprs_gmm_prim_upper_down(gmm_prim); + OSMO_ASSERT(rc == 0); + + /* 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 */ printf("==== %s() [end] ====\n", __func__); } @@ -90,6 +263,7 @@ 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); diff --git a/tests/gmm/gmm_prim_test.err b/tests/gmm/gmm_prim_test.err index e69de29..0256edf 100644 --- a/tests/gmm/gmm_prim_test.err +++ b/tests/gmm/gmm_prim_test.err @@ -0,0 +1,18 @@ +DLGLOBAL INFO Rx from upper layers: GMMREG-ATTACH.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 GMME(PTMSI-00000000) Tx GMM ATTACH REQUEST (new P-TMSI=0x00000000) +DLGLOBAL INFO GMM_MS{Deregistered}: Received Event ATTACH_REQUESTED +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 40b5ffc..91bcaeb 100644 --- a/tests/gmm/gmm_prim_test.ok +++ b/tests/gmm/gmm_prim_test.ok @@ -1,2 +1,10 @@ ==== test_gmm_prim_ms() [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_ms() [end] ==== -- To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32021 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmo-gprs Gerrit-Branch: master Gerrit-Change-Id: I212053b3a3f27ef7d63503c3d5ef08453b2d2056 Gerrit-Change-Number: 32021 Gerrit-PatchSet: 7 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Hoernchen <ewild(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
[M] Change in osmo-bsc[master]: bts: bts: Explain Ericsson's interface switch (IS)
by dexter 24 Mar '23

24 Mar '23
Attention is currently required from: osmith, keith. dexter has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/32029 ) Change subject: bts: bts: Explain Ericsson's interface switch (IS) ...................................................................... Patch Set 3: (2 comments) File doc/manuals/chapters/bts.adoc: https://gerrit.osmocom.org/c/osmo-bsc/+/32029/comment/a9323180_881b90cb PS1, Line 784: to the outside must be aligned to E1 timeslot boarders. > borders. […] Done File doc/manuals/chapters/bts.adoc: https://gerrit.osmocom.org/c/osmo-bsc/+/32029/comment/58ad215d_f9239d5e PS2, Line 700: [options="header",cols="45%,25%,25%"] > these need to add up to 100%, with this patch the build passes: […] Done -- To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/32029 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-bsc Gerrit-Branch: master Gerrit-Change-Id: Ib6ebd7fdfe9063c0d8cacf53ffd27f6099d9038a Gerrit-Change-Number: 32029 Gerrit-PatchSet: 3 Gerrit-Owner: dexter <pmaier(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: keith <keith(a)rhizomatica.org> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-CC: osmith <osmith(a)sysmocom.de> Gerrit-Attention: osmith <osmith(a)sysmocom.de> Gerrit-Attention: keith <keith(a)rhizomatica.org> Gerrit-Comment-Date: Fri, 24 Mar 2023 13:22:47 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Comment-In-Reply-To: osmith <osmith(a)sysmocom.de> Comment-In-Reply-To: keith <keith(a)rhizomatica.org> Gerrit-MessageType: comment
1 0
0 0
[M] Change in osmo-bsc[master]: bts: bts: Explain Ericsson's interface switch (IS)
by dexter 24 Mar '23

24 Mar '23
Attention is currently required from: osmith, keith. Hello Jenkins Builder, laforge, keith, I'd like you to reexamine a change. Please visit https://gerrit.osmocom.org/c/osmo-bsc/+/32029 to look at the new patch set (#3). Change subject: bts: bts: Explain Ericsson's interface switch (IS) ...................................................................... bts: bts: Explain Ericsson's interface switch (IS) The built in interface switch in ericsson RBS base stations no where explained. From the example configuration files alone it is not possible to understand how the IS configuration works. Let's add a chapter that explains how the IS configuration works. Related: OS#5198 Change-Id: Ib6ebd7fdfe9063c0d8cacf53ffd27f6099d9038a --- M doc/manuals/chapters/bts-examples.adoc M doc/manuals/chapters/bts.adoc 2 files changed, 153 insertions(+), 1 deletion(-) git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/29/32029/3 -- To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/32029 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-bsc Gerrit-Branch: master Gerrit-Change-Id: Ib6ebd7fdfe9063c0d8cacf53ffd27f6099d9038a Gerrit-Change-Number: 32029 Gerrit-PatchSet: 3 Gerrit-Owner: dexter <pmaier(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: keith <keith(a)rhizomatica.org> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-CC: osmith <osmith(a)sysmocom.de> Gerrit-Attention: osmith <osmith(a)sysmocom.de> Gerrit-Attention: keith <keith(a)rhizomatica.org> Gerrit-MessageType: newpatchset
1 0
0 0
[S] Change in libosmocore[master]: rate_ctr: Add rate_ctr_add2() similar to rate_ctr_inc2()
by laforge 24 Mar '23

24 Mar '23
laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/libosmocore/+/32048 ) Change subject: rate_ctr: Add rate_ctr_add2() similar to rate_ctr_inc2() ...................................................................... rate_ctr: Add rate_ctr_add2() similar to rate_ctr_inc2() The convenience wrapper relieves the caller from manually resolving the individual counter, and instead specify just the counter group and the index. Change-Id: If93e8b4fb0b86a87358f32d2b45438ca1887e9f3 --- M include/osmocom/core/rate_ctr.h 1 file changed, 22 insertions(+), 0 deletions(-) git pull ssh://gerrit.osmocom.org:29418/libosmocore refs/changes/48/32048/1 diff --git a/include/osmocom/core/rate_ctr.h b/include/osmocom/core/rate_ctr.h index d944cc0..0a3eb2c 100644 --- a/include/osmocom/core/rate_ctr.h +++ b/include/osmocom/core/rate_ctr.h @@ -86,6 +86,15 @@ * \param inc quantity to increment \a ctr by */ void rate_ctr_add(struct rate_ctr *ctr, int inc); +/*! Increment the counter by \a inc + * \param ctrg \ref rate_ctr_group of counter + * \param idx index into \a ctrg counter group + * \param inc quantity to increment \a ctr by */ +static inline void rate_ctr_add2(struct rate_ctr_group *ctrg, unsigned int idx, int inc) +{ + rate_ctr_add(rate_ctr_group_get_ctr(ctrg, idx), inc); +} + /*! Increment the counter by 1 * \param ctr \ref rate_ctr to increment */ static inline void rate_ctr_inc(struct rate_ctr *ctr) -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/32048 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: If93e8b4fb0b86a87358f32d2b45438ca1887e9f3 Gerrit-Change-Number: 32048 Gerrit-PatchSet: 1 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-MessageType: newchange
1 0
0 0
[S] Change in libosmocore[master]: gsmtap.h: Define a packet type for encapsulation of GSM RLP frames
by laforge 24 Mar '23

24 Mar '23
laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/31805 ) Change subject: gsmtap.h: Define a packet type for encapsulation of GSM RLP frames ...................................................................... gsmtap.h: Define a packet type for encapsulation of GSM RLP frames This allows us to feed RLP frames (occurring in GSM CSD) into wireshark for dissection. Change-Id: Ibb7f0731c31e5a5cd2911f733da5510ce0f3a1d6 --- M include/osmocom/core/gsmtap.h M src/core/gsmtap_util.c 2 files changed, 14 insertions(+), 0 deletions(-) Approvals: fixeria: Looks good to me, approved Jenkins Builder: Verified diff --git a/include/osmocom/core/gsmtap.h b/include/osmocom/core/gsmtap.h index b0985f0..2387b20 100644 --- a/include/osmocom/core/gsmtap.h +++ b/include/osmocom/core/gsmtap.h @@ -49,6 +49,7 @@ #define GSMTAP_TYPE_QC_DIAG 0x11 /* Qualcomm DIAG frame */ #define GSMTAP_TYPE_LTE_NAS 0x12 /* LTE Non-Access Stratum */ #define GSMTAP_TYPE_E1T1 0x13 /* E1/T1 Lines */ +#define GSMTAP_TYPE_GSM_RLP 0x14 /* GSM RLP frames as per 3GPP TS 24.022 */ /* ====== DO NOT MAKE UNAPPROVED MODIFICATIONS HERE ===== */ diff --git a/src/core/gsmtap_util.c b/src/core/gsmtap_util.c index 2e0b84e..a95c795 100644 --- a/src/core/gsmtap_util.c +++ b/src/core/gsmtap_util.c @@ -595,6 +595,7 @@ { GSMTAP_TYPE_QC_DIAG, "Qualcomm DIAG" }, { GSMTAP_TYPE_LTE_NAS, "LTE Non-Access Stratum" }, { GSMTAP_TYPE_E1T1, "E1/T1 lines" }, + { GSMTAP_TYPE_GSM_RLP, "GSM Radio Link Protocol" }, { 0, NULL } }; -- To view, visit https://gerrit.osmocom.org/c/libosmocore/+/31805 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmocore Gerrit-Branch: master Gerrit-Change-Id: Ibb7f0731c31e5a5cd2911f733da5510ce0f3a1d6 Gerrit-Change-Number: 31805 Gerrit-PatchSet: 3 Gerrit-Owner: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
[M] Change in osmo-bsc[master]: bts: bts: Explain Ericsson's interface switch (IS)
by osmith 24 Mar '23

24 Mar '23
Attention is currently required from: dexter. osmith has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/32029 ) Change subject: bts: bts: Explain Ericsson's interface switch (IS) ...................................................................... Patch Set 2: (2 comments) Patchset: PS2: This File doc/manuals/chapters/bts.adoc: https://gerrit.osmocom.org/c/osmo-bsc/+/32029/comment/8240fa09_d3eee67d PS2, Line 700: [options="header",cols="45%,25%,25%"] these need to add up to 100%, with this patch the build passes: ``` diff --git a/doc/manuals/chapters/bts.adoc b/doc/manuals/chapters/bts.adoc index 111c5051f..195fc32b6 100644 --- a/doc/manuals/chapters/bts.adoc +++ b/doc/manuals/chapters/bts.adoc @@ -697,7 +697,7 @@ will repeat itself. This means the next usable ICP can be found at an offset of 128. .External connections of a BTS with two E1 ports -[options="header",cols="45%,25%,25%"] +[options="header",cols="50%,25%,25%"] |=== |Function |Subslot offset (ICP) |ICP count |E1 port A |4 |124 @@ -713,7 +713,7 @@ used to serve a single air interface timeslot. The two sets of ICPs must not be mixed. Only one set may be used at a time. .ICPs to use TRU with 16kbps subslots per TRAU -[options="header",cols="45%,25%,25%"] +[options="header",cols="50%,25%,25%"] |=== |Function |Subslot offset (ICP) |ICP count |TRU-0, RSL/OML |512 |4 @@ -748,7 +748,7 @@ connections on the other end may contain gaps and do not have to be consecutive. .ICPs to use TRU with 64kbps subslots per TRAU -[options="header",cols="45%,25%,25%"] +[options="header",cols="50%,25%,25%"] |=== |Function |Subslot offset (ICP) |ICP count |TRU-0, RSL/OML |712 |4 @@ -781,4 +781,4 @@ NOTE: In case voice TRAU frames are transferred, only the first of the four 16kbps subslots is used. When the timeslot is switched to GPRS/EGPRS, the full 64kbps bandwidth will be used. This also means that the set of four ICPs per TRAU must be connected consecutively. Also the connection -to the outside must be aligned to E1 timeslot borders. \ No newline at end of file +to the outside must be aligned to E1 timeslot borders. ``` -- To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/32029 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-bsc Gerrit-Branch: master Gerrit-Change-Id: Ib6ebd7fdfe9063c0d8cacf53ffd27f6099d9038a Gerrit-Change-Number: 32029 Gerrit-PatchSet: 2 Gerrit-Owner: dexter <pmaier(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: keith <keith(a)rhizomatica.org> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-CC: osmith <osmith(a)sysmocom.de> Gerrit-Attention: dexter <pmaier(a)sysmocom.de> Gerrit-Comment-Date: Fri, 24 Mar 2023 13:05:07 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: No Gerrit-MessageType: comment
1 0
0 0
[M] Change in osmo-bts[master]: rsl: rsl_handle_chan_mod_ie(): add missing GSM48_CMODE_* values
by fixeria 24 Mar '23

24 Mar '23
fixeria has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/32027 ) Change subject: rsl: rsl_handle_chan_mod_ie(): add missing GSM48_CMODE_* values ...................................................................... rsl: rsl_handle_chan_mod_ie(): add missing GSM48_CMODE_* values Change-Id: Iec397f1ef4cb5ac1c48abf869f54e272ed0fbb55 Depends: libosmocore.git I6adda28698c0e479ef20f5d090c1f7f76a2ec97e Depends: libosmocore.git Ia6b428e5b6aaecf151cbfa980b89eff6d0fe6006 Related: OS#1572 --- M src/common/rsl.c 1 file changed, 53 insertions(+), 17 deletions(-) Approvals: Jenkins Builder: Verified laforge: Looks good to me, but someone else must approve pespin: Looks good to me, approved diff --git a/src/common/rsl.c b/src/common/rsl.c index c537998..8f1ff5d 100644 --- a/src/common/rsl.c +++ b/src/common/rsl.c @@ -161,14 +161,14 @@ lchan->tch_mode = GSM48_CMODE_SPEECH_AMR; break; case RSL_CMODE(RSL_CMOD_SPD_SPEECH, RSL_CMOD_SP_GSM4): + lchan->tch_mode = GSM48_CMODE_SPEECH_V4; + break; case RSL_CMODE(RSL_CMOD_SPD_SPEECH, RSL_CMOD_SP_GSM5): + lchan->tch_mode = GSM48_CMODE_SPEECH_V5; + break; case RSL_CMODE(RSL_CMOD_SPD_SPEECH, RSL_CMOD_SP_GSM6): - /* TODO: also handle RSL_CMOD_SP_{GSM4,GSM5,GSM6} */ - LOGPLCHAN(lchan, DRSL, LOGL_ERROR, "Channel Mode IE contains " - "unhandled speech coding algorithm 0x%02x\n", - cm->chan_rate); - *cause = RSL_ERR_IE_CONTENT; - return -ENOTSUP; + lchan->tch_mode = GSM48_CMODE_SPEECH_V6; + break; /* If octet 4 indicates non-transparent data */ case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_NT_14k5): @@ -181,35 +181,59 @@ lchan->tch_mode = GSM48_CMODE_DATA_6k0; break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_NT_43k5): + lchan->tch_mode = GSM48_CMODE_DATA_43k5; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_NT_28k8): + /* 28.8 kbit/s services, 29.0 kbit/s radio interface rate */ + lchan->tch_mode = GSM48_CMODE_DATA_29k0; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_NTA_43k5_14k5): + lchan->tch_mode = GSM48_CMODE_DATA_43k5_14k5; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_NTA_29k0_14k5): + lchan->tch_mode = GSM48_CMODE_DATA_29k0_14k5; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_NTA_43k5_29k0): + lchan->tch_mode = GSM48_CMODE_DATA_43k5_29k0; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_NTA_14k5_43k5): + lchan->tch_mode = GSM48_CMODE_DATA_14k5_43k5; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_NTA_14k5_29k0): + lchan->tch_mode = GSM48_CMODE_DATA_14k5_29k0; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_NTA_29k0_43k5): - /* TODO: also handle other non-transparent data rates */ - LOGPLCHAN(lchan, DRSL, LOGL_ERROR, "Channel Mode IE contains " - "unhandled non-transparent CSD data rate 0x%02x\n", - cm->chan_rate & 0x3f); - *cause = RSL_ERR_IE_CONTENT; - return -ENOTSUP; + lchan->tch_mode = GSM48_CMODE_DATA_29k0_43k5; + break; /* If octet 4 indicates transparent data */ case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_T_32000): + /* 32.0 kbit/s services, 32.0 kbit/s radio interface rate */ + lchan->tch_mode = GSM48_CMODE_DATA_32k0; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_T_29000): + /* 29.0 kbit/s services, 29.0 kbit/s radio interface rate */ + lchan->tch_mode = GSM48_CMODE_DATA_29k0; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_T_14400): + /* 14.4 kbit/s services, 14.5 kbit/s radio interface rate */ + lchan->tch_mode = GSM48_CMODE_DATA_14k5; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_T_9600): + /* 9.6 kbit/s services, 12.0 kbit/s radio interface rate */ + lchan->tch_mode = GSM48_CMODE_DATA_12k0; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_T_4800): + /* 4.8 kbit/s services, 6.0 kbit/s radio interface rate */ + lchan->tch_mode = GSM48_CMODE_DATA_6k0; + break; case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_T_2400): case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_T_1200): case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_T_600): case RSL_CMODE(RSL_CMOD_SPD_DATA, RSL_CMOD_CSD_T_1200_75): - LOGPLCHAN(lchan, DRSL, LOGL_ERROR, "Channel Mode IE contains " - "unhandled transparent CSD data rate 0x%02x\n", - cm->chan_rate & 0x3f); - *cause = RSL_ERR_IE_CONTENT; - return -ENOTSUP; + /* 2.4 kbit/s *and less* services, 3.6 kbit/s radio interface rate */ + lchan->tch_mode = GSM48_CMODE_DATA_3k6; + break; default: LOGPLCHAN(lchan, DRSL, LOGL_ERROR, "Channel Mode IE contains " -- To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/32027 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-bts Gerrit-Branch: master Gerrit-Change-Id: Iec397f1ef4cb5ac1c48abf869f54e272ed0fbb55 Gerrit-Change-Number: 32027 Gerrit-PatchSet: 3 Gerrit-Owner: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-MessageType: merged
1 0
0 0
[XL] Change in libosmo-gprs[master]: gmm: Initial implementation of GPRS Attach
by fixeria 24 Mar '23

24 Mar '23
Attention is currently required from: Hoernchen, pespin. fixeria has posted comments on this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32021 ) Change subject: gmm: Initial implementation of GPRS Attach ...................................................................... Patch Set 7: Code-Review+2 (1 comment) File libosmo-gprs-gmm.pc.in: https://gerrit.osmocom.org/c/libosmo-gprs/+/32021/comment/7de04942_275f0539 PS1, Line 9: libosmo-gprs-llc > So is it fine now? can this merged? Done -- To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32021 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmo-gprs Gerrit-Branch: master Gerrit-Change-Id: I212053b3a3f27ef7d63503c3d5ef08453b2d2056 Gerrit-Change-Number: 32021 Gerrit-PatchSet: 7 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Hoernchen <ewild(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Attention: Hoernchen <ewild(a)sysmocom.de> Gerrit-Attention: pespin <pespin(a)sysmocom.de> Gerrit-Comment-Date: Fri, 24 Mar 2023 12:54:18 +0000 Gerrit-HasComments: Yes Gerrit-Has-Labels: Yes Comment-In-Reply-To: pespin <pespin(a)sysmocom.de> Comment-In-Reply-To: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-MessageType: comment
1 0
0 0
[XL] Change in libosmo-gprs[master]: gmm: Initial implementation of GPRS Attach
by pespin 24 Mar '23

24 Mar '23
Attention is currently required from: Hoernchen, fixeria. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/libosmo-gprs/+/32021 ) Change subject: gmm: Initial implementation of GPRS Attach ...................................................................... Patch Set 7: (1 comment) File libosmo-gprs-gmm.pc.in: https://gerrit.osmocom.org/c/libosmo-gprs/+/32021/comment/0191810f_21dd63ad PS1, Line 9: libosmo-gprs-llc > Ah, right. Somehow I thought I am commenting to file `contrib/libosmo-gprs.spec.in`. So is it fine now? can this merged? -- To view, visit https://gerrit.osmocom.org/c/libosmo-gprs/+/32021 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: libosmo-gprs Gerrit-Branch: master Gerrit-Change-Id: I212053b3a3f27ef7d63503c3d5ef08453b2d2056 Gerrit-Change-Number: 32021 Gerrit-PatchSet: 7 Gerrit-Owner: pespin <pespin(a)sysmocom.de> Gerrit-Reviewer: Hoernchen <ewild(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Reviewer: laforge <laforge(a)osmocom.org> Gerrit-Attention: Hoernchen <ewild(a)sysmocom.de> Gerrit-Attention: fixeria <vyanitskiy(a)sysmocom.de> Gerrit-Comment-Date: Fri, 24 Mar 2023 12:34:20 +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
0 0
[S] Change in osmo-pcu[master]: doc: overview: put BTS and PCU on the same rank
by pespin 24 Mar '23

24 Mar '23
Attention is currently required from: dexter. pespin has posted comments on this change. ( https://gerrit.osmocom.org/c/osmo-pcu/+/32047 ) Change subject: doc: overview: put BTS and PCU on the same rank ...................................................................... Patch Set 1: Code-Review+1 -- To view, visit https://gerrit.osmocom.org/c/osmo-pcu/+/32047 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-pcu Gerrit-Branch: master Gerrit-Change-Id: Ifa170f3956b4629765a88ed62e877a204541d9ea Gerrit-Change-Number: 32047 Gerrit-PatchSet: 1 Gerrit-Owner: dexter <pmaier(a)sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: pespin <pespin(a)sysmocom.de> Gerrit-Attention: dexter <pmaier(a)sysmocom.de> Gerrit-Comment-Date: Fri, 24 Mar 2023 12:32:37 +0000 Gerrit-HasComments: No Gerrit-Has-Labels: Yes Gerrit-MessageType: comment
1 0
0 0
  • ← Newer
  • 1
  • ...
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • ...
  • 365
  • Older →

HyperKitty Powered by HyperKitty version 1.3.12.