#pragma once /* 3GPP TS 24.007, private header */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern int g_sm_log_cat[_OSMO_GPRS_SM_LOGC_MAX]; #define LOGSM(lvl, fmt, args...) LOGP(g_sm_log_cat[OSMO_GPRS_SM_LOGC_SM], lvl, fmt, ## args) #define msgb_sm_prim(msg) ((struct osmo_gprs_sm_prim *)(msg)->l1h) /* 10.5.6.4 Packet data protocol address */ enum gprs_sm_pdp_addr_org { GPRS_SM_PDP_ADDR_ORG_ETSI = 0x00, GPRS_SM_PDP_ADDR_ORG_IETF = 0x01, GPRS_SM_PDP_ADDR_ORG_EMPTY = 0x0f, /* All other values are reserved. */ }; /* 10.5.6.4 Packet data protocol address */ enum gprs_sm_pdp_addr_etsi_type { GPRS_SM_PDP_ADDR_ETSI_RESERVED = 00, /* used in earlier version of this protocol */ GPRS_SM_PDP_ADDR_ETSI_PPP = 0x01, GPRS_SM_PDP_ADDR_ETSI_NON_IP = 0x02, /* All other values are reserved in this version of the protocol. */ }; struct gprs_sm_pdp_addr { #if OSMO_IS_LITTLE_ENDIAN uint8_t organization:4, /* enum gprs_sm_pdp_addr_org */ spare:4; #elif OSMO_IS_BIG_ENDIAN /* auto-generated from the little endian part above (libosmocore/contrib/struct_endianness.py) */ uint8_t spare:4, organization:4; #endif uint8_t type; /* osmo_gprs_sm_pdp_addr_{etsi,ietf}_type */ union { /* IPv4 */ uint32_t addr; /* IPv6 */ uint8_t addr6[16]; /* IPv4v6 */ struct { uint32_t addr; uint8_t addr6[16]; } __attribute__ ((packed)) both; }; } __attribute__ ((packed)); struct gprs_sm_ms; struct gprs_sm_ctx { enum osmo_gprs_sm_location location; osmo_gprs_sm_prim_up_cb sm_up_cb; void *sm_up_cb_user_data; osmo_gprs_sm_prim_sndcp_up_cb sm_sndcp_up_cb; void *sm_sndcp_up_cb_user_data; osmo_gprs_sm_prim_down_cb sm_down_cb; void *sm_down_cb_user_data; osmo_gprs_sm_prim_gmm_down_cb sm_gmm_down_cb; void *sm_gmm_down_cb_user_data; struct osmo_tdef *T_defs; /* timers controlled by SM layer */ struct llist_head ms_list; /* list of struct gprs_sm_ms->list */ uint32_t next_sess_id; }; extern struct gprs_sm_ctx *g_sm_ctx; /* SM Entity, PDP CTX */ struct gprs_sm_entity { struct gprs_sm_ms *ms; /* backpointer */ uint32_t sess_id; uint8_t nsapi; enum osmo_gprs_sm_llc_sapi llc_sapi; enum osmo_gprs_sm_pdp_addr_ietf_type pdp_addr_ietf_type; struct osmo_sockaddr pdp_addr_v4; struct osmo_sockaddr pdp_addr_v6; uint8_t radio_prio; /* TS 24.008 10.5.7.2 */ uint8_t qos[OSMO_GPRS_SM_QOS_MAXLEN]; uint8_t qos_len; char apn[OSMO_GPRS_SM_APN_MAXLEN]; uint8_t pco[OSMO_GPRS_SM_MBIFORM_MAXLEN]; uint8_t pco_len; uint8_t ti; /* transaction identifier */ struct gprs_sm_ms_fsm_ctx ms_fsm; }; /* Mobile Station: */ struct gprs_sm_ms { struct llist_head list; /* item in (struct gprs_sm_ctx)->ms_list */ uint32_t ms_id; struct gprs_sm_entity *pdp[OSMO_GPRS_SM_PDP_MAXNSAPI]; struct { uint32_t ptmsi; uint32_t ptmsi_sig; uint32_t tlli; char imsi[OSMO_IMSI_BUF_SIZE]; char imei[GSM23003_IMEI_NUM_DIGITS + 1]; char imeisv[GSM23003_IMEISV_NUM_DIGITS+1]; struct gprs_ra_id ra; /* TS 24.008 10.5.5.15 (decoded) */ } gmm; }; /* 10.5.6.2 Network service access point identifier */ static inline bool gprs_sm_nsapi_is_valid(uint8_t nsapi) { return nsapi >= 5 && nsapi <= 15; } static inline struct gprs_sm_entity *gprs_sm_ms_get_pdp_ctx(struct gprs_sm_ms *ms, uint8_t nsapi) { OSMO_ASSERT(gprs_sm_nsapi_is_valid(nsapi)); return ms->pdp[nsapi]; } /* sm_prim.c: */ int gprs_sm_prim_call_up_cb(struct osmo_gprs_sm_prim *sm_prim); int gprs_sm_prim_call_down_cb(struct osmo_gprs_sm_prim *sm_prim); int gprs_sm_prim_call_gmm_down_cb(struct osmo_gprs_gmm_prim *gmm_prim); int gprs_sm_prim_call_sndcp_up_cb(struct osmo_gprs_sndcp_prim *sndcp_prim); struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_act_cnf(void); struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_act_ind(void); struct osmo_gprs_sm_prim *gprs_sm_prim_alloc_smreg_pdp_deact_ind(void); /* sm.c: */ struct gprs_sm_ms *gprs_sm_ms_alloc(uint32_t ms_id); void gprs_sm_ms_free(struct gprs_sm_ms *ms); struct gprs_sm_ms *gprs_sm_find_ms_by_id(uint32_t ms_id); struct gprs_sm_ms *gprs_sm_find_ms_by_tlli(uint32_t tlli); struct gprs_sm_entity *gprs_sm_entity_alloc(struct gprs_sm_ms *ms, uint32_t nsapi); void gprs_sm_entity_free(struct gprs_sm_entity *sme); struct gprs_sm_entity *gprs_sm_find_sme_by_sess_id(uint32_t sess_id); void gprs_sm_handle_ie_pdp_ctx_status(struct gprs_sm_ms *ms, const uint8_t *pdp_status); int gprs_sm_submit_gmmsm_assign_req(const struct gprs_sm_entity *sme); int gprs_sm_submit_smreg_pdp_act_cnf(const struct gprs_sm_entity *sme, enum gsm48_gsm_cause cause); int gprs_sm_submit_smreg_pdp_deact_ind(const struct gprs_sm_entity *sme, enum gsm48_gsm_cause cause); int gprs_sm_submit_snsm_act_ind(const struct gprs_sm_entity *sme); int gprs_sm_submit_snsm_deact_ind(const struct gprs_sm_entity *sme); int gprs_sm_tx_act_pdp_ctx_req(struct gprs_sm_entity *sme); int gprs_sm_rx(struct gprs_sm_entity *sme, struct gsm48_hdr *gh, unsigned int len); #define LOGMS(ms, level, fmt, args...) \ LOGSM(level, "MS(ID-%u) " fmt, \ ms->ms_id, \ ## args) #define LOGSME(sme, level, fmt, args...) \ LOGSM(level, "PDP(ID-%u:NSAPI-%u) " fmt, \ sme->ms->ms_id, \ sme->nsapi, \ ## args)