diff options
Diffstat (limited to 'include/osmo-bts')
35 files changed, 1209 insertions, 565 deletions
diff --git a/include/osmo-bts/Makefile.am b/include/osmo-bts/Makefile.am index d52c9aa4..cbd0fc37 100644 --- a/include/osmo-bts/Makefile.am +++ b/include/osmo-bts/Makefile.am @@ -1,9 +1,11 @@ noinst_HEADERS = \ abis.h \ abis_osmo.h \ + asci.h \ bts.h \ bts_model.h \ bts_shutdown_fsm.h \ + bts_sm.h \ bts_trx.h \ gsm_data.h \ logging.h \ @@ -11,6 +13,7 @@ noinst_HEADERS = \ oml.h \ paging.h \ rsl.h \ + rtp_input_preen.h \ signal.h \ vty.h \ amr.h \ @@ -21,7 +24,9 @@ noinst_HEADERS = \ tx_power.h \ control_if.h \ cbch.h \ + csd_v110.h \ l1sap.h \ + lchan.h \ power_control.h \ scheduler.h \ scheduler_backend.h \ @@ -29,4 +34,6 @@ noinst_HEADERS = \ dtx_dl_amr_fsm.h \ ta_control.h \ nm_common_fsm.h \ + notification.h \ + osmux.h \ $(NULL) diff --git a/include/osmo-bts/abis.h b/include/osmo-bts/abis.h index 62407ece..40707cd1 100644 --- a/include/osmo-bts/abis.h +++ b/include/osmo-bts/abis.h @@ -6,19 +6,15 @@ #include <osmo-bts/gsm_data.h> -#define OML_RETRY_TIMER 5 -#define OML_PING_TIMER 20 - -enum { - LINK_STATE_IDLE = 0, - LINK_STATE_RETRYING, - LINK_STATE_CONNECTING, - LINK_STATE_CONNECT, +enum abis_link_fsm_event { + ABIS_LINK_EV_SIGN_LINK_OML_UP, + ABIS_LINK_EV_SIGN_LINK_DOWN, + ABIS_LINK_EV_VTY_RM_ADDR, /* data: struct bsc_oml_host* being removed */ }; void abis_init(struct gsm_bts *bts); -struct e1inp_line *abis_open(struct gsm_bts *bts, char *dst_host, - char *model_name); +int abis_open(struct gsm_bts *bts, char *model_name); + int abis_oml_sendmsg(struct msgb *msg); diff --git a/include/osmo-bts/amr.h b/include/osmo-bts/amr.h index f3132874..3fa4b8f2 100644 --- a/include/osmo-bts/amr.h +++ b/include/osmo-bts/amr.h @@ -14,5 +14,6 @@ int amr_parse_mr_conf(struct amr_multirate_conf *amr_mrc, void amr_set_mode_pref(uint8_t *data, const struct amr_multirate_conf *amr_mrc, uint8_t cmi, uint8_t cmr); unsigned int amr_get_initial_mode(struct gsm_lchan *lchan); +void amr_init_mr_conf_def(struct gsm_lchan *lchan); #endif /* _OSMO_BTS_AMR_H */ diff --git a/include/osmo-bts/asci.h b/include/osmo-bts/asci.h new file mode 100644 index 00000000..99802962 --- /dev/null +++ b/include/osmo-bts/asci.h @@ -0,0 +1,43 @@ +#pragma once +#include <stdint.h> + +#include <osmo-bts/lchan.h> + +enum { + VGCS_TALKER_NONE = 0, + VGCS_TALKER_WAIT_FRAME, + VGCS_TALKER_ACTIVE, +}; + +void vgcs_rach(struct gsm_lchan *lchan, uint8_t ra, uint8_t acc_delay, uint32_t fn); + +void vgcs_lchan_activate(struct gsm_lchan *lchan); + +void vgcs_lchan_react(struct gsm_lchan *lchan); + +void vgcs_talker_frame(struct gsm_lchan *lchan); + +void vgcs_talker_reset(struct gsm_lchan *lchan, bool ul_access); + +void vgcs_listener_reset(struct gsm_lchan *lchan); + +static inline bool vgcs_is_uplink_free(struct gsm_lchan *lchan) +{ + return lchan->asci.uplink_free; +} + +static inline void vgcs_uplink_free_get(struct gsm_lchan *lchan, uint8_t *msg) +{ + memcpy(msg, lchan->asci.uplink_free_msg, GSM_MACBLOCK_LEN); +} + +static inline void vgcs_uplink_free_set(struct gsm_lchan *lchan, uint8_t *msg) +{ + memcpy(lchan->asci.uplink_free_msg, msg, GSM_MACBLOCK_LEN); + lchan->asci.uplink_free = true; +} + +static inline void vgcs_uplink_free_reset(struct gsm_lchan *lchan) +{ + lchan->asci.uplink_free = false; +} diff --git a/include/osmo-bts/bts.h b/include/osmo-bts/bts.h index 6a61d015..8a5fb820 100644 --- a/include/osmo-bts/bts.h +++ b/include/osmo-bts/bts.h @@ -5,6 +5,7 @@ #include <osmocom/core/socket.h> #include <osmo-bts/gsm_data.h> #include <osmo-bts/bts_trx.h> +#include <osmo-bts/osmux.h> struct gsm_bts_trx; @@ -24,11 +25,21 @@ enum { BTS_CTR_RACH_RCVD, BTS_CTR_RACH_DROP, BTS_CTR_RACH_HO, + BTS_CTR_RACH_VGCS, BTS_CTR_RACH_CS, BTS_CTR_RACH_PS, BTS_CTR_AGCH_RCVD, BTS_CTR_AGCH_SENT, BTS_CTR_AGCH_DELETED, + + BTS_CTR_RTP_RX_TOTAL, + BTS_CTR_RTP_RX_MARKER, + BTS_CTR_RTP_RX_DROP_PREEN, + BTS_CTR_RTP_RX_DROP_LOOPBACK, + BTS_CTR_RTP_RX_DROP_OVERFLOW, + BTS_CTR_RTP_RX_DROP_V110_DEC, + BTS_CTR_RTP_TX_TOTAL, + BTS_CTR_RTP_TX_MARKER, }; /* Used by OML layer for BTS Attribute reporting */ @@ -52,34 +63,28 @@ enum gsm_bts_type_variant { }; const char *btsvariant2str(enum gsm_bts_type_variant v); -/* TODO: add a brief description of this flag */ -#define BTS_INTERNAL_FLAG_MS_PWR_CTRL_DSP (1 << 0) -/* When this flag is set then the measurement data is included in - * (PRIM_PH_DATA) and struct ph_tch_param (PRIM_TCH). Otherwise the - * measurement data is passed using a separate MPH INFO MEAS IND. - * (See also ticket: OS#2977) */ -#define BTS_INTERNAL_FLAG_MEAS_PAYLOAD_COMB (1 << 1) -/* Whether the BTS model requires RadioCarrier MO to be in Enabled state - * (OPSTARTed) before OPSTARTing the RadioChannel MOs. See OS#5157 */ -#define BTS_INTERNAL_FLAG_NM_RCHANNEL_DEPENDS_RCARRIER (1 << 2) +enum bts_impl_flag { + /* TODO: add a brief description of this flag */ + BTS_INTERNAL_FLAG_MS_PWR_CTRL_DSP, + /* When this flag is set then the measurement data is included in + * (PRIM_PH_DATA) and struct ph_tch_param (PRIM_TCH). Otherwise the + * measurement data is passed using a separate MPH INFO MEAS IND. + * (See also ticket: OS#2977) */ + BTS_INTERNAL_FLAG_MEAS_PAYLOAD_COMB, + /* Whether the BTS model requires RadioCarrier MO to be in Enabled state + * (OPSTARTed) before OPSTARTing the RadioChannel MOs. See OS#5157 */ + BTS_INTERNAL_FLAG_NM_RCHANNEL_DEPENDS_RCARRIER, + /* Whether the BTS model reports interference measurements to L1SAP. */ + BTS_INTERNAL_FLAG_INTERF_MEAS, + + _BTS_INTERNAL_FLAG_NUM, /* must be at the end */ +}; /* BTS implementation flags (internal use, not exposed via OML) */ #define bts_internal_flag_get(bts, flag) \ - ((bts->flags & (typeof(bts->flags)) flag) != 0) + ((bts->flags & (typeof(bts->flags))(1 << flag)) != 0) #define bts_internal_flag_set(bts, flag) \ - bts->flags |= (typeof(bts->flags)) flag - -struct gsm_bts_gprs_nsvc { - struct gsm_bts *bts; - /* data read via VTY config file, to configure the BTS - * via OML from BSC */ - int id; - uint16_t nsvci; - struct osmo_sockaddr local; /* on the BTS */ - struct osmo_sockaddr remote; /* on the SGSN */ - - struct gsm_abis_mo mo; -}; + bts->flags |= (typeof(bts->flags))(1 << flag) struct gprs_rlc_cfg { uint16_t parameter[_NUM_RLC_PAR]; @@ -128,14 +133,28 @@ struct bts_power_ctrl_params { } pf; }; -/* BTS Site Manager */ -struct gsm_bts_sm { +/* GPRS CELL; ip.access specific NM Object */ +struct gsm_gprs_cell { struct gsm_abis_mo mo; + uint16_t bvci; + uint8_t timer[11]; + struct gprs_rlc_cfg rlc_cfg; + struct { + uint32_t gprs_codings; /* see NM_IPAC_F_GPRS_CODING_* flags */ + } support; +}; + +/* Struct that holds one OML-Address (Address of the BSC) */ +struct bsc_oml_host { + struct llist_head list; + char *addr; }; +#define BTS_PCU_SOCK_WQUEUE_LEN_DEFAULT 100 + /* One BTS */ struct gsm_bts { - /* list header in net->bts_list */ + /* list header in g_bts_sm->bts_list */ struct llist_head list; /* number of the BTS in network */ @@ -149,6 +168,7 @@ struct gsm_bts { /* Base Station Identification Code (BSIC), lower 3 bits is BCC, * which is used as TSC for the CCCH */ uint8_t bsic; + bool bsic_configured; /* type of BTS */ enum gsm_bts_type_variant variant; enum gsm_band band; @@ -184,7 +204,7 @@ struct gsm_bts { /* CCCH is on C0 */ struct gsm_bts_trx *c0; - struct gsm_bts_sm site_mgr; + struct gsm_bts_sm *site_mgr; /* bitmask of all SI that are present/valid in si_buf */ uint32_t si_valid; @@ -214,18 +234,7 @@ struct gsm_bts { /* Not entirely sure how ip.access specific this is */ struct { - struct { - struct gsm_abis_mo mo; - uint16_t nsei; - uint8_t timer[7]; - } nse; - struct { - struct gsm_abis_mo mo; - uint16_t bvci; - uint8_t timer[11]; - struct gprs_rlc_cfg rlc_cfg; - } cell; - struct gsm_bts_gprs_nsvc nsvc[2]; + struct gsm_gprs_cell cell; uint8_t rac; } gprs; @@ -241,8 +250,9 @@ struct gsm_bts { int16_t boundary[6]; uint8_t intave; } interference; - unsigned int t200_ms[7]; + uint32_t t200_fn[7]; unsigned int t3105_ms; + unsigned int t3115_ms; /* VGCS UPLINK GRANT repeat timer */ struct { uint8_t overload_period; struct { @@ -265,6 +275,7 @@ struct gsm_bts { } rach; } load; uint8_t ny1; + uint8_t ny2; /* maximum number of repetitions for the VGCS UPLINK GRANT */ uint8_t max_ta; /* AGCH queuing */ @@ -294,9 +305,17 @@ struct gsm_bts { bool pni; /* Primary Notification Identifier */ } etws; + /* Advanced Speech Call Items (VBS/VGCS) + NCH related bits */ + struct { + int pos_nch; /* position of the NCH or < 0, if not available */ + uint8_t nln, nln_status; /* current notification list number and status */ + struct llist_head notifications; + int notification_entries; /* current number of entries in the list */ + int notification_count; /* counter to count all entries */ + } asci; + struct paging_state *paging_state; - char *bsc_oml_host; - struct llist_head oml_queue; + struct llist_head bsc_oml_hosts; unsigned int rtp_jitter_buf_ms; bool rtp_jitter_adaptive; @@ -306,8 +325,13 @@ struct gsm_bts { int rtp_ip_dscp; int rtp_priority; + bool rtp_nogaps_mode; /* emit RTP stream without any gaps */ + bool use_ul_ecu; /* "rtp internal-uplink-ecu" option */ + bool emit_hr_rfc5993; + struct { uint8_t ciphers; /* flags A5/1==0x1, A5/2==0x2, A5/3==0x4 */ + uint8_t max_ta; /* maximum timing advance */ } support; struct { uint8_t tc4_ctr; @@ -352,17 +376,26 @@ struct gsm_bts { struct { char *sock_path; + unsigned int sock_wqueue_len_max; } pcu; /* GSMTAP Um logging (disabled by default) */ struct { struct gsmtap_inst *inst; char *remote_host; + char *local_host; uint32_t sapi_mask; uint8_t sapi_acch; + bool rlp; + bool rlp_skip_null; } gsmtap; + struct osmux_state osmux; + struct osmo_fsm_inst *shutdown_fi; /* FSM instance to manage shutdown procedure during process exit */ + bool shutdown_fi_exit_proc; /* exit process when shutdown_fsm is finished? */ + bool shutdown_fi_skip_power_ramp; /* Skip power ramping and change power in one step? */ + struct osmo_fsm_inst *abis_link_fi; /* FSM instance to manage abis connection during process startup and link failure */ struct osmo_tdef *T_defs; /* Timer defines */ void *model_priv; /* Allocated by bts_model, contains model specific data pointer */ @@ -375,40 +408,47 @@ extern void *tall_bts_ctx; #define GSM_BTS_HAS_SI(bts, i) ((bts)->si_valid & (1 << i)) #define GSM_BTS_SI(bts, i) (void *)((bts)->si_buf[i][0]) -static inline struct gsm_bts *gsm_bts_sm_get_bts(struct gsm_bts_sm *site_mgr) { - return (struct gsm_bts *)container_of(site_mgr, struct gsm_bts, site_mgr); +static inline struct gsm_bts *gsm_gprs_cell_get_bts(struct gsm_gprs_cell *cell) +{ + return (struct gsm_bts *)container_of(cell, struct gsm_bts, gprs.cell); } -struct gsm_bts *gsm_bts_alloc(void *talloc_ctx, uint8_t bts_num); -struct gsm_bts *gsm_bts_num(const struct gsm_network *net, int num); +struct gsm_bts *gsm_bts_alloc(struct gsm_bts_sm *bts_sm, uint8_t bts_num); +struct gsm_bts *gsm_bts_num(const struct gsm_bts_sm *bts_sm, int num); int bts_init(struct gsm_bts *bts); void bts_shutdown(struct gsm_bts *bts, const char *reason); +void bts_shutdown_ext(struct gsm_bts *bts, const char *reason, bool exit_proc, bool skip_power_ramp); int bts_link_estab(struct gsm_bts *bts); int bts_agch_enqueue(struct gsm_bts *bts, struct msgb *msg); -struct msgb *bts_agch_dequeue(struct gsm_bts *bts); int bts_agch_max_queue_length(int T, int bcch_conf); -int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt, - int is_ag_res); + +enum ccch_msgt { + CCCH_MSGT_AGCH, + CCCH_MSGT_PCH, + CCCH_MSGT_NCH, +}; + +int bts_ccch_copy_msg(struct gsm_bts *bts, uint8_t *out_buf, struct gsm_time *gt, enum ccch_msgt ccch); int bts_supports_cipher(struct gsm_bts *bts, int rsl_cipher); uint8_t *bts_sysinfo_get(struct gsm_bts *bts, const struct gsm_time *g_time); void regenerate_si3_restoctets(struct gsm_bts *bts); void regenerate_si4_restoctets(struct gsm_bts *bts); int get_si4_ro_offset(const uint8_t *si4_buf); -uint8_t *lchan_sacch_get(struct gsm_lchan *lchan); -int lchan_init_lapdm(struct gsm_lchan *lchan); void load_timer_start(struct gsm_bts *bts); +void load_timer_stop(struct gsm_bts *bts); +bool load_timer_is_running(const struct gsm_bts *bts); void bts_update_status(enum bts_global_status which, int on); struct gsm_time *get_time(struct gsm_bts *bts); int bts_main(int argc, char **argv); -int bts_supports_cm(const struct gsm_bts *bts, - const struct rsl_ie_chan_mode *cm); +bool bts_supports_cm(const struct gsm_bts *bts, + const struct rsl_ie_chan_mode *cm); int32_t bts_get_avg_fn_advance(const struct gsm_bts *bts); @@ -417,4 +457,11 @@ struct gsm_lchan *gsm_bts_get_cbch(struct gsm_bts *bts); int bts_set_c0_pwr_red(struct gsm_bts *bts, const uint8_t red); +/* Context information to be put in the control buffer (db) of the AGCH msg + * buffer */ +struct bts_agch_msg_cb { + uint32_t msg_id; + bool confirm; +} __attribute__ ((packed)); + #endif /* _BTS_H */ diff --git a/include/osmo-bts/bts_model.h b/include/osmo-bts/bts_model.h index ef93fdad..673eb5b1 100644 --- a/include/osmo-bts/bts_model.h +++ b/include/osmo-bts/bts_model.h @@ -5,6 +5,7 @@ #include <osmocom/gsm/tlv.h> #include <osmocom/gsm/gsm_utils.h> +#include <osmocom/gsm/protocol/gsm_12_21.h> #include <osmo-bts/gsm_data.h> @@ -20,8 +21,8 @@ int bts_model_check_oml(struct gsm_bts *bts, uint8_t msg_type, struct tlv_parsed *old_attr, struct tlv_parsed *new_attr, void *obj); -int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, - struct tlv_parsed *new_attr, int obj_kind, void *obj); +int bts_model_apply_oml(struct gsm_bts *bts, const struct msgb *msg, + struct gsm_abis_mo *mo, void *obj); int bts_model_opstart(struct gsm_bts *bts, struct gsm_abis_mo *mo, void *obj); diff --git a/include/osmo-bts/bts_shutdown_fsm.h b/include/osmo-bts/bts_shutdown_fsm.h index 1e74ac6b..553267dc 100644 --- a/include/osmo-bts/bts_shutdown_fsm.h +++ b/include/osmo-bts/bts_shutdown_fsm.h @@ -1,6 +1,6 @@ /* BTS shutdown FSM */ -/* (C) 2020 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> +/* (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * Author: Pau Espin Pedrol <pespin@sysmocom.de> * * All Rights Reserved @@ -13,7 +13,7 @@ * 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 General Public License for more details. + * 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/>. @@ -24,7 +24,6 @@ #include <osmocom/core/fsm.h> -/* 3GPP TS 24.008 ยง 4.1.3.3 GMM mobility management states on the network side */ enum bts_shutdown_fsm_states { BTS_SHUTDOWN_ST_NONE, BTS_SHUTDOWN_ST_WAIT_RAMP_DOWN_COMPL, @@ -39,3 +38,6 @@ enum bts_shutdown_fsm_events { }; extern struct osmo_fsm bts_shutdown_fsm; + +struct gsm_bts; +bool bts_shutdown_in_progress(const struct gsm_bts *bts); diff --git a/include/osmo-bts/bts_sm.h b/include/osmo-bts/bts_sm.h new file mode 100644 index 00000000..e6610a5e --- /dev/null +++ b/include/osmo-bts/bts_sm.h @@ -0,0 +1,48 @@ +#pragma once + +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/socket.h> +#include <osmocom/gsm/gsm23003.h> + +#include <osmo-bts/oml.h> + +struct pcu_sock_state; + +/* GPRS NSVC; ip.access specific NM Object */ +struct gsm_gprs_nse; +struct gsm_gprs_nsvc { + struct gsm_abis_mo mo; + struct gsm_gprs_nse *nse; + /* data read via VTY config file, to configure the BTS + * via OML from BSC */ + int id; + uint16_t nsvci; + struct osmo_sockaddr local; /* on the BTS */ + struct osmo_sockaddr remote; /* on the SGSN */ +}; + +/* GPRS NSE; ip.access specific NM Object */ +struct gsm_gprs_nse { + struct gsm_abis_mo mo; + uint16_t nsei; + uint8_t timer[7]; + struct gsm_gprs_nsvc nsvc[2]; +}; + +struct gsm_bts *gsm_gprs_nse_get_bts(const struct gsm_gprs_nse *nse); + +/* BTS Site Manager */ +struct gsm_bts_sm { + struct gsm_abis_mo mo; + struct llist_head bts_list; + unsigned int num_bts; + struct osmo_plmn_id plmn; + struct { + struct pcu_sock_state *pcu_state; + struct gsm_gprs_nse nse; + } gprs; +}; + +extern struct gsm_bts_sm *g_bts_sm; + +struct gsm_bts_sm *gsm_bts_sm_alloc(void *talloc_ctx); diff --git a/include/osmo-bts/bts_trx.h b/include/osmo-bts/bts_trx.h index f033573f..9d3a748e 100644 --- a/include/osmo-bts/bts_trx.h +++ b/include/osmo-bts/bts_trx.h @@ -1,9 +1,16 @@ #pragma once +#include <osmocom/core/sockaddr_str.h> #include <osmo-bts/gsm_data.h> struct gsm_bts_bb_trx { struct gsm_abis_mo mo; + /* how do we talk RSL with this TRX? */ + struct { + struct osmo_sockaddr_str rem_addrstr; + uint8_t tei; + struct e1inp_sign_link *link; + } rsl; }; /* One TRX in a BTS */ @@ -16,9 +23,6 @@ struct gsm_bts_trx { uint8_t nr; /* human readable name / description */ char *description; - /* how do we talk RSL with this TRX? */ - uint8_t rsl_tei; - struct e1inp_sign_link *rsl_link; /* NM Radio Carrier and Baseband Transciever */ struct gsm_abis_mo mo; @@ -27,9 +31,10 @@ struct gsm_bts_trx { uint16_t arfcn; int nominal_power; /* in dBm */ unsigned int max_power_red; /* in actual dB */ - uint8_t max_power_backoff_8psk; /* in actual dB OC-2G only */ - uint8_t c0_idle_power_red; /* in actual dB OC-2G only */ + uint8_t max_power_backoff_8psk; /* in actual dB OC-2G only */ + uint8_t c0_idle_power_red; /* in actual dB OC-2G only */ + uint8_t ta_ctrl_interval; /* 1 step is 2 SACCH periods */ struct trx_power_params power_params; struct gsm_power_ctrl_params *bs_dpc_params; /* BS Dynamic Power Control */ @@ -39,6 +44,12 @@ struct gsm_bts_trx { /* The associated PHY instance */ struct phy_instance *pinst; + struct { + uint32_t freq_bands; /* see NM_IPAC_F_FREQ_BAND_* flags */ + uint32_t chan_types; /* see NM_IPAC_F_CHANT_* flags */ + uint32_t chan_modes; /* see NM_IPAC_F_CHANM_* flags */ + } support; + struct gsm_bts_trx_ts ts[TRX_NR_TS]; }; @@ -49,6 +60,7 @@ static inline struct gsm_bts_trx *gsm_bts_bb_trx_get_trx(struct gsm_bts_bb_trx * struct gsm_bts_trx *gsm_bts_trx_alloc(struct gsm_bts *bts); struct gsm_bts_trx *gsm_bts_trx_num(const struct gsm_bts *bts, int num); void gsm_bts_trx_init_shadow_ts(struct gsm_bts_trx *trx); +void gsm_bts_trx_free_shadow_ts(struct gsm_bts_trx *trx); char *gsm_trx_name(const struct gsm_bts_trx *trx); const char *gsm_trx_unit_id(struct gsm_bts_trx *trx); @@ -56,6 +68,7 @@ int trx_link_estab(struct gsm_bts_trx *trx); void trx_operability_update(struct gsm_bts_trx *trx); uint8_t num_agch(const struct gsm_bts_trx *trx, const char * arg); +int pos_nch(const struct gsm_bts_trx *trx, const char *arg); bool trx_ms_pwr_ctrl_is_osmo(const struct gsm_bts_trx *trx); #define LOGPTRX(trx, ss, lvl, fmt, args...) LOGP(ss, lvl, "%s " fmt, gsm_trx_name(trx), ## args) diff --git a/include/osmo-bts/cbch.h b/include/osmo-bts/cbch.h index 6bba5fa2..d5521f06 100644 --- a/include/osmo-bts/cbch.h +++ b/include/osmo-bts/cbch.h @@ -21,3 +21,5 @@ int bts_process_smscb_cmd(struct gsm_bts *bts, struct rsl_ie_cb_cmd_type cmd_typ /* call-back from bts model specific code when it wants to obtain a CBCH * block for a given gsm_time. outbuf must have 23 bytes of space. */ int bts_cbch_get(struct gsm_bts *bts, uint8_t *outbuf, struct gsm_time *g_time); + +void bts_cbch_reset(struct gsm_bts *bts); diff --git a/include/osmo-bts/control_if.h b/include/osmo-bts/control_if.h index 490c87af..f6d877bc 100644 --- a/include/osmo-bts/control_if.h +++ b/include/osmo-bts/control_if.h @@ -1,5 +1,4 @@ #pragma once int bts_ctrl_cmds_install(struct gsm_bts *bts); -struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts, - const char *bind_addr, uint16_t port); +struct ctrl_handle *bts_controlif_setup(struct gsm_bts *bts, uint16_t port); diff --git a/include/osmo-bts/csd_v110.h b/include/osmo-bts/csd_v110.h new file mode 100644 index 00000000..f6be0ae2 --- /dev/null +++ b/include/osmo-bts/csd_v110.h @@ -0,0 +1,23 @@ +#pragma once + +/* RFC4040 "clearmode" RTP payload length */ +#define RFC4040_RTP_PLEN 160 + +struct gsm_lchan; + +struct csd_v110_frame_desc { + uint16_t num_blocks; + uint16_t num_bits; +}; + +struct csd_v110_lchan_desc { + struct csd_v110_frame_desc fr; + struct csd_v110_frame_desc hr; +}; + +extern const struct csd_v110_lchan_desc csd_v110_lchan_desc[256]; + +int csd_v110_rtp_encode(const struct gsm_lchan *lchan, uint8_t *rtp, + const uint8_t *data, size_t data_len); +int csd_v110_rtp_decode(const struct gsm_lchan *lchan, uint8_t *data, + const uint8_t *rtp, size_t rtp_len); diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h index 0ed63612..164c89fd 100644 --- a/include/osmo-bts/gsm_data.h +++ b/include/osmo-bts/gsm_data.h @@ -9,15 +9,13 @@ #include <osmocom/core/statistics.h> #include <osmocom/core/utils.h> #include <osmocom/core/linuxlist.h> -#include <osmocom/codec/ecu.h> -#include <osmocom/gsm/lapdm.h> +#include <osmocom/core/tdef.h> #include <osmocom/gsm/gsm23003.h> #include <osmocom/gsm/gsm0502.h> #include <osmocom/gsm/gsm_utils.h> #include <osmocom/gsm/tlv.h> #include <osmocom/gsm/rxlev_stat.h> #include <osmocom/gsm/sysinfo.h> -#include <osmocom/gsm/meas_rep.h> #include <osmocom/gsm/bts_features.h> #include <osmocom/gsm/gsm48_rest_octets.h> #include <osmocom/gsm/protocol/gsm_04_08.h> @@ -29,6 +27,7 @@ #include <osmo-bts/paging.h> #include <osmo-bts/tx_power.h> #include <osmo-bts/oml.h> +#include <osmo-bts/lchan.h> #define GSM_FR_BITS 260 #define GSM_EFR_BITS 244 @@ -42,23 +41,6 @@ #define GSM_BTS_AGCH_QUEUE_LOW_LEVEL_DEFAULT 41 #define GSM_BTS_AGCH_QUEUE_HIGH_LEVEL_DEFAULT 91 -#define LOGPLCHAN(lchan, ss, lvl, fmt, args...) LOGP(ss, lvl, "%s " fmt, gsm_lchan_name(lchan), ## args) - -struct gsm_network { - struct llist_head bts_list; - unsigned int num_bts; - struct osmo_plmn_id plmn; - struct pcu_sock_state *pcu_state; -}; - -enum lchan_ciph_state { - LCHAN_CIPH_NONE, - LCHAN_CIPH_RX_REQ, - LCHAN_CIPH_RX_CONF, - LCHAN_CIPH_RXTX_REQ, - LCHAN_CIPH_RX_CONF_TX_REQ, - LCHAN_CIPH_RXTX_CONF, -}; /* 16 is the max. number of SI2quater messages according to 3GPP TS 44.018 Table 10.5.2.33b.1: 4-bit index is used (2#1111 = 10#15) */ @@ -70,355 +52,58 @@ enum lchan_ciph_state { /* lchans 0..3 are SDCCH in combined channel configuration, use 4 as magic number for BCCH hack - see osmo-bts-../oml.c:opstart_compl() */ #define CCCH_LCHAN 4 +#define CBCH_LCHAN 2 #define TRX_NR_TS 8 #define TS_MAX_LCHAN 8 #define MAX_VERSION_LENGTH 64 -struct gsm_lchan; -struct osmo_rtp_socket; -struct pcu_sock_state; -struct smscb_msg; - -#define MAX_A5_KEY_LEN (128/8) -#define RSL_ENC_ALG_A5(x) (x+1) - -/* state of a logical channel */ -enum gsm_lchan_state { - LCHAN_S_NONE, /* channel is not active */ - LCHAN_S_ACT_REQ, /* channel activation requested */ - LCHAN_S_ACTIVE, /* channel is active and operational */ - LCHAN_S_REL_REQ, /* channel release has been requested */ - LCHAN_S_REL_ERR, /* channel is in an error state */ - LCHAN_S_BROKEN, /* channel is somehow unusable */ - LCHAN_S_INACTIVE, /* channel is set inactive */ -}; - -#define MAX_NUM_UL_MEAS 104 -#define LC_UL_M_F_L1_VALID (1 << 0) -#define LC_UL_M_F_RES_VALID (1 << 1) -#define LC_UL_M_F_OSMO_EXT_VALID (1 << 2) - -struct bts_ul_meas { - /* BER in units of 0.01%: 10.000 == 100% ber, 0 == 0% ber */ - uint16_t ber10k; - /* timing advance offset (in 1/256 bits) */ - int16_t ta_offs_256bits; - /* C/I ratio in dB */ - float c_i; - /* flags */ - uint8_t is_sub:1; - /* RSSI in dBm * -1 */ - uint8_t inv_rssi; -}; - -struct amr_mode { - uint8_t mode; - uint8_t threshold; - uint8_t hysteresis; -}; - -struct amr_multirate_conf { - uint8_t gsm48_ie[2]; - struct amr_mode ms_mode[4]; - struct amr_mode bts_mode[4]; - uint8_t num_modes; -}; - -enum lchan_csd_mode { - LCHAN_CSD_M_NT, - LCHAN_CSD_M_T_1200_75, - LCHAN_CSD_M_T_600, - LCHAN_CSD_M_T_1200, - LCHAN_CSD_M_T_2400, - LCHAN_CSD_M_T_9600, - LCHAN_CSD_M_T_14400, - LCHAN_CSD_M_T_29000, - LCHAN_CSD_M_T_32000, -}; - -/* State of the SAPIs in the lchan */ -enum lchan_sapi_state { - LCHAN_SAPI_S_NONE, - LCHAN_SAPI_S_REQ, - LCHAN_SAPI_S_ASSIGNED, - LCHAN_SAPI_S_REL, - LCHAN_SAPI_S_ERROR, -}; - -/* What kind of release/activation is done? A silent one for - * the PDCH or one triggered through RSL? */ -enum lchan_rel_act_kind { - LCHAN_REL_ACT_RSL, - LCHAN_REL_ACT_PCU, - LCHAN_REL_ACT_OML, - LCHAN_REL_ACT_REACT, /* remove once auto-activation hack is removed from opstart_compl() */ -}; - -struct gsm_rep_facch { - struct msgb *msg; - uint32_t fn; -}; - -/* MS/BS Power related measurement averaging algo */ -enum gsm_power_ctrl_meas_avg_algo { - GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE = 0x00, - GSM_PWR_CTRL_MEAS_AVG_ALGO_UNWEIGHTED = 0x01, - GSM_PWR_CTRL_MEAS_AVG_ALGO_WEIGHTED = 0x02, - GSM_PWR_CTRL_MEAS_AVG_ALGO_MOD_MEDIAN = 0x03, - /* EWMA is an Osmocom specific algo */ - GSM_PWR_CTRL_MEAS_AVG_ALGO_OSMO_EWMA = 0x04, -}; - -/* MS/BS Power related measurement parameters */ -struct gsm_power_ctrl_meas_params { - /* Thresholds (see 3GPP TS 45.008, section A.3.2.1) */ - uint8_t lower_thresh; /* lower (decreasing) direction */ - uint8_t upper_thresh; /* upper (increasing) direction */ - - /* Threshold Comparators for lower (decreasing) direction */ - uint8_t lower_cmp_p; /* P1 for RxLev, P3 for RxQual */ - uint8_t lower_cmp_n; /* N1 for RxLev, N3 for RxQual */ - /* Threshold Comparators for upper (increasing) direction */ - uint8_t upper_cmp_p; /* P2 for RxLev, P4 for RxQual */ - uint8_t upper_cmp_n; /* N2 for RxLev, N4 for RxQual */ - - /* Hreqave and Hreqt (see 3GPP TS 45.008, Annex A) */ - uint8_t h_reqave; - uint8_t h_reqt; - - /* AVG algorithm and its specific parameters */ - enum gsm_power_ctrl_meas_avg_algo algo; - union { - /* Exponentially Weighted Moving Average */ - struct { - /* Smoothing factor: higher the value - less smoothing */ - uint8_t alpha; /* 1 .. 99 (in %) */ - } ewma; - }; -}; - -/* MS/BS Power Control parameters */ -struct gsm_power_ctrl_params { - /* Minimum interval between power level changes */ - uint8_t ctrl_interval; /* 1 step is 2 SACCH periods */ - - /* Power change step size (maximum) */ - uint8_t inc_step_size_db; /* increasing direction */ - uint8_t red_step_size_db; /* reducing direction */ - - /* Measurement averaging parameters for RxLev & RxQual */ - struct gsm_power_ctrl_meas_params rxqual_meas; - struct gsm_power_ctrl_meas_params rxlev_meas; -}; - -/* Default MS/BS Power Control parameters */ -extern const struct gsm_power_ctrl_params power_ctrl_params_def; - -/* Measurement pre-processing state */ -struct gsm_power_ctrl_meas_proc_state { - /* Number of measurements processed */ - unsigned int meas_num; - /* Algorithm specific data */ - union { - struct { - /* Scaled up 100 times average value */ - int Avg100; - } ewma; - }; -}; - -struct lchan_power_ctrl_state { - /* Dynamic Power Control parameters (NULL in static mode) */ - const struct gsm_power_ctrl_params *dpc_params; - /* Measurement pre-processing state (for dynamic mode) */ - struct gsm_power_ctrl_meas_proc_state rxlev_meas_proc; - /* Number of SACCH blocks to skip (for dynamic mode) */ - int skip_block_num; - - /* Depending on the context (MS or BS power control), fields 'current' and 'max' - * reflect either the MS power level (magic numbers), or BS Power reduction level - * (attenuation, in dB). */ - uint8_t current; - uint8_t max; -}; - -struct gsm_lchan { - /* The TS that we're part of */ - struct gsm_bts_trx_ts *ts; - /* The logical subslot number in the TS */ - uint8_t nr; - /* The logical channel type */ - enum gsm_chan_t type; - /* RSL channel mode */ - enum rsl_cmod_spd rsl_cmode; - /* If TCH, traffic channel mode */ - enum gsm48_chan_mode tch_mode; - enum lchan_csd_mode csd_mode; - /* State */ - enum gsm_lchan_state state; - const char *broken_reason; - /* Encryption information */ - struct { - uint8_t alg_id; - uint8_t key_len; - uint8_t key[MAX_A5_KEY_LEN]; - } encr; - - struct { - uint32_t bound_ip; - uint32_t connect_ip; - uint16_t bound_port; - uint16_t connect_port; - uint16_t conn_id; - uint8_t rtp_payload; - uint8_t rtp_payload2; - uint8_t speech_mode; - struct osmo_rtp_socket *rtp_socket; - } abis_ip; - - uint8_t rqd_ta; - - char *name; - - /* For handover, activation is described in 3GPP TS 48.058 4.1.3 and 4.1.4: - * - * | | Access || transmit | activate - * | MS Power | Delay || on main channel | dl SACCH - * ---------------------------------------------------------------------- - * async ho no * --> yes no - * async ho yes * --> yes may be started - * sync ho no no --> yes no - * sync ho yes no --> yes may be started - * sync ho yes yes --> yes shall be started - * - * Always start the main channel immediately. - * want_dl_sacch_active indicates whether dl SACCH should be activated on CHAN ACT. - */ - bool want_dl_sacch_active; - - /* Number of different GsmL1_Sapi_t used in osmo_bts_sysmo is 23. - * Currently we don't share these headers so this is a magic number. */ - struct llist_head sapi_cmds; - uint8_t sapis_dl[23]; - uint8_t sapis_ul[23]; - struct lapdm_channel lapdm_ch; - struct llist_head dl_tch_queue; - struct { - /* bitmask of all SI that are present/valid in si_buf */ - uint32_t valid; - /* bitmask of all SI that do not mirror the BTS-global SI values */ - uint32_t overridden; - uint32_t last; - /* buffers where we put the pre-computed SI: - SI2Q_MAX_NUM is the max number of SI2quater messages (see 3GPP TS 44.018) */ - sysinfo_buf_t buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM]; - } si; - struct { - uint8_t flags; - /* RSL measurement result number, 0 at lchan_act */ - uint8_t res_nr; - /* number of measurements stored in array below */ - uint8_t num_ul_meas; - struct bts_ul_meas uplink[MAX_NUM_UL_MEAS]; - /* last L1 header from the MS */ - struct rsl_l1_info l1_info; - struct gsm_meas_rep_unidir ul_res; - int16_t ms_toa256; - /* Frame number of the last measurement indication receceived */ - uint32_t last_fn; - /* Osmocom extended measurement results, see LC_UL_M_F_EXTD_VALID */ - struct { - /* minimum value of toa256 during measurement period */ - int16_t toa256_min; - /* maximum value of toa256 during measurement period */ - int16_t toa256_max; - /* standard deviation of toa256 value during measurement period */ - uint16_t toa256_std_dev; - } ext; - /* Interference levels reported by PHY (in dBm) */ - int16_t interf_meas_dbm[31]; /* Intave max is 31 */ - uint8_t interf_meas_num; - } meas; - struct { - struct amr_multirate_conf amr_mr; - struct { - struct osmo_fsm_inst *dl_amr_fsm; - /* TCH cache */ - uint8_t cache[20]; - /* FACCH cache */ - uint8_t facch[GSM_MACBLOCK_LEN]; - uint8_t len; - uint32_t fn; - bool is_update; - /* set for each SID frame to detect talkspurt for codecs - without explicit ONSET event */ - bool ul_sid; - /* indicates if DTXd was active during DL measurement - period */ - bool dl_active; - /* last UL SPEECH resume flag */ - bool is_speech_resume; - } dtx; - uint8_t last_cmr; - uint32_t last_fn; - - /* SLOT #0 and #1 to store FACCH for repetition */ - struct gsm_rep_facch rep_facch[2]; - - } tch; - - /* 3GPP TS 48.058 ยง 9.3.37: [0; 255] ok, -1 means invalid*/ - int16_t ms_t_offs; - /* 3GPP TS 45.010 ยง 1.2 round trip propagation delay (in symbols) or -1 */ - int16_t p_offs; - - /* BTS-side ciphering state (rx only, bi-directional, ...) */ - uint8_t ciph_state; - uint8_t ciph_ns; - uint8_t loopback; - struct { - uint8_t active; - uint8_t ref; - /* T3105: PHYS INF retransmission */ - struct osmo_timer_list t3105; - /* counts up to Ny1 */ - unsigned int phys_info_count; - } ho; - /* S counter for link loss */ - int s; - /* Kind of the release/activation. E.g. RSL or PCU */ - enum lchan_rel_act_kind rel_act_kind; - /* RTP header Marker bit to indicate beginning of speech after pause */ - bool rtp_tx_marker; - - /* MS/BS power control state */ - struct lchan_power_ctrl_state ms_power_ctrl; - struct lchan_power_ctrl_state bs_power_ctrl; - - /* MS/BS Dynamic Power Control parameters */ - struct gsm_power_ctrl_params ms_dpc_params; - struct gsm_power_ctrl_params bs_dpc_params; - - struct msgb *pending_rel_ind_msg; - - /* ECU (Error Concealment Unit) state */ - struct osmo_ecu_state *ecu_state; - - struct abis_rsl_osmo_rep_acch_cap repeated_acch_capability; - bool repeated_dl_facch_active; - bool repeated_ul_sacch_active; - bool repeated_dl_sacch_active; - - /* Message buffer to store DL-SACCH repeation candidate */ - struct msgb *rep_sacch; -}; - -extern const struct value_string lchan_ciph_state_names[]; -static inline const char *lchan_ciph_state_name(uint8_t state) { - return get_value_string(lchan_ciph_state_names, state); -} +/* NM_IPAC_F_CHANT_* mask for NM_IPAC_EIE_CHAN_TYPES (common) */ +#define NM_IPAC_MASK_CHANT_COMMON \ + (NM_IPAC_F_CHANT_TCHF | \ + NM_IPAC_F_CHANT_TCHH | \ + NM_IPAC_F_CHANT_SDCCH8 | \ + NM_IPAC_F_CHANT_BCCH | \ + NM_IPAC_F_CHANT_BCCH_SDCCH4) +/* NM_IPAC_F_CHANM_SPEECH_* mask for NM_IPAC_EIE_CHAN_MODES */ +#define NM_IPAC_MASK_CHANM_SPEECH \ + (NM_IPAC_F_CHANM_SPEECH_FS | \ + NM_IPAC_F_CHANM_SPEECH_EFS | \ + NM_IPAC_F_CHANM_SPEECH_AFS | \ + NM_IPAC_F_CHANM_SPEECH_HS | \ + NM_IPAC_F_CHANM_SPEECH_AHS) +/* NM_IPAC_F_CHANM_CSD_NT_* mask for NM_IPAC_EIE_CHAN_MODES */ +#define NM_IPAC_MASK_CHANM_CSD_NT \ + (NM_IPAC_F_CHANM_CSD_NT_4k8 | \ + NM_IPAC_F_CHANM_CSD_NT_9k6 | \ + NM_IPAC_F_CHANM_CSD_NT_14k4) +/* NM_IPAC_F_CHANM_CSD_T_* mask for NM_IPAC_EIE_CHAN_MODES */ +#define NM_IPAC_MASK_CHANM_CSD_T \ + (NM_IPAC_F_CHANM_CSD_T_1200_75 | \ + NM_IPAC_F_CHANM_CSD_T_600 | \ + NM_IPAC_F_CHANM_CSD_T_1k2 | \ + NM_IPAC_F_CHANM_CSD_T_2k4 | \ + NM_IPAC_F_CHANM_CSD_T_4k8 | \ + NM_IPAC_F_CHANM_CSD_T_9k6 | \ + NM_IPAC_F_CHANM_CSD_T_14k4) +/* NM_IPAC_F_GPRS_CODING_CS[1-4] mask for NM_IPAC_EIE_GPRS_CODING */ +#define NM_IPAC_MASK_GPRS_CODING_CS \ + (NM_IPAC_F_GPRS_CODING_CS1 | \ + NM_IPAC_F_GPRS_CODING_CS2 | \ + NM_IPAC_F_GPRS_CODING_CS3 | \ + NM_IPAC_F_GPRS_CODING_CS4) +/* NM_IPAC_F_GPRS_CODING_MCS[1-9] mask for NM_IPAC_EIE_GPRS_CODING */ +#define NM_IPAC_MASK_GPRS_CODING_MCS \ + (NM_IPAC_F_GPRS_CODING_MCS1 | \ + NM_IPAC_F_GPRS_CODING_MCS2 | \ + NM_IPAC_F_GPRS_CODING_MCS3 | \ + NM_IPAC_F_GPRS_CODING_MCS4 | \ + NM_IPAC_F_GPRS_CODING_MCS5 | \ + NM_IPAC_F_GPRS_CODING_MCS6 | \ + NM_IPAC_F_GPRS_CODING_MCS7 | \ + NM_IPAC_F_GPRS_CODING_MCS8 | \ + NM_IPAC_F_GPRS_CODING_MCS9) enum gsm_bts_trx_ts_flags { TS_F_PDCH_ACTIVE = 0x1000, @@ -439,7 +124,6 @@ struct gsm_bts_trx_ts { struct { enum gsm_phys_chan_config pchan_is; enum gsm_phys_chan_config pchan_want; - struct msgb *pending_chan_activ; } dyn; unsigned int flags; @@ -447,7 +131,10 @@ struct gsm_bts_trx_ts { /* Training Sequence Code (range 0..7) */ uint8_t tsc_oml; /* configured via OML */ - uint8_t tsc; /* currently in use */ + bool tsc_oml_configured; + uint8_t tsc_rsl; /* configured via RSL (Osmo extension) */ + bool tsc_rsl_configured; + uint8_t tsc; /* TSC currently in use. Preference: RSL, OML, BTS-BSIC-OML */ /* Training Sequence Set (range 0..3) */ uint8_t tsc_set; @@ -479,8 +166,6 @@ struct gsm_bts_trx_ts { struct gsm_lchan lchan[TS_MAX_LCHAN]; }; -#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i][0]) - enum gprs_rlc_par { RLC_T3142, RLC_T3169, @@ -517,6 +202,9 @@ enum gprs_cs { * OML connection will cause a special warning to be logged. */ #define OSMO_BTS_OML_CONN_EARLY_DISCONNECT 10 /* in seconds */ +extern struct osmo_tdef_group bts_tdef_groups[]; +extern struct osmo_tdef bts_T_defs[]; +extern struct osmo_tdef abis_T_defs[]; extern const struct value_string gsm_pchant_names[13]; extern const struct value_string gsm_pchant_descs[13]; @@ -524,8 +212,6 @@ const char *gsm_pchan_name(enum gsm_phys_chan_config c); const char *gsm_lchant_name(enum gsm_chan_t c); char *gsm_ts_name(const struct gsm_bts_trx_ts *ts); char *gsm_ts_and_pchan_name(const struct gsm_bts_trx_ts *ts); -void gsm_lchan_name_update(struct gsm_lchan *lchan); -const char *gsm_lchans_name(enum gsm_lchan_state s); #define GSM_TS_NAME_FMT \ "bts=%u,trx=%u,ts=%u" "%s" @@ -533,18 +219,6 @@ const char *gsm_lchans_name(enum gsm_lchan_state s); (ts)->trx->bts->nr, (ts)->trx->nr, (ts)->nr, \ (ts)->vamos.is_shadow ? ",shadow" : "" -static inline char *gsm_lchan_name(const struct gsm_lchan *lchan) -{ - return lchan->name; -} - -uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan); -uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan, - enum gsm_phys_chan_config as_pchan); - -void gsm_lchan_interf_meas_push(struct gsm_lchan *lchan, int dbm); -int gsm_lchan_interf_meas_calc_band(struct gsm_lchan *lchan); - #define BSIC2BCC(bsic) ((bsic) & 0x07) #define BTS_TSC(bts) BSIC2BCC((bts)->bsic) @@ -555,9 +229,6 @@ enum gsm_phys_chan_config ts_pchan(const struct gsm_bts_trx_ts *ts); uint8_t ts_subslots(const struct gsm_bts_trx_ts *ts); bool ts_is_tch(const struct gsm_bts_trx_ts *ts); -int lchan2ecu_codec(const struct gsm_lchan *lchan); - -void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state); int conf_lchans_as_pchan(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config pchan); @@ -566,16 +237,8 @@ int conf_lchans_as_pchan(struct gsm_bts_trx_ts *ts, bool ts_is_pdch(const struct gsm_bts_trx_ts *ts); -static inline bool lchan_is_dcch(const struct gsm_lchan *lchan) -{ - switch (lchan->type) { - case GSM_LCHAN_SDCCH: - case GSM_LCHAN_TCH_F: - case GSM_LCHAN_TCH_H: - return true; - default: - return false; - } -} +void gsm_ts_apply_configured_tsc(struct gsm_bts_trx_ts *ts); + +void gsm_ts_release(struct gsm_bts_trx_ts *ts); #endif /* _GSM_DATA_H */ diff --git a/include/osmo-bts/l1sap.h b/include/osmo-bts/l1sap.h index f78d1143..34259bd3 100644 --- a/include/osmo-bts/l1sap.h +++ b/include/osmo-bts/l1sap.h @@ -4,6 +4,8 @@ #include <osmocom/gsm/protocol/gsm_04_08.h> #include <osmocom/gsm/protocol/gsm_08_58.h> +#define L1SAP_MSGB_HEADROOM 128 + /* lchan link ID */ #define LID_SACCH 0x40 #define LID_DEDIC 0x00 @@ -96,10 +98,11 @@ void l1sap_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl, uint32_t timestamp, bool marker); /* channel control */ -int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr, struct tlv_parsed *tp); +int l1sap_chan_act(struct gsm_bts_trx *trx, uint8_t chan_nr); int l1sap_chan_rel(struct gsm_bts_trx *trx, uint8_t chan_nr); int l1sap_chan_deact_sacch(struct gsm_bts_trx *trx, uint8_t chan_nr); int l1sap_chan_modify(struct gsm_bts_trx *trx, uint8_t chan_nr); +int l1sap_uplink_access(struct gsm_lchan *lchan, bool active); enum l1sap_common_sapi { L1SAP_COMMON_SAPI_UNKNOWN, @@ -139,12 +142,11 @@ int add_l1sap_header(struct gsm_bts_trx *trx, struct msgb *rmsg, #define msgb_l1sap_prim(msg) ((struct osmo_phsap_prim *)(msg)->l1h) +void radio_link_timeout_reset(struct gsm_lchan *lchan); + int bts_check_for_first_ciphrd(struct gsm_lchan *lchan, uint8_t *data, int len); -int is_ccch_for_agch(struct gsm_bts_trx *trx, uint32_t fn); - -void repeated_dl_facch_active_decision(struct gsm_lchan *lchan, - const uint8_t *l3, size_t l3_len); +enum ccch_msgt get_ccch_msgt(struct gsm_bts_trx *trx, uint32_t fn); #endif /* L1SAP_H */ diff --git a/include/osmo-bts/lchan.h b/include/osmo-bts/lchan.h new file mode 100644 index 00000000..585483bd --- /dev/null +++ b/include/osmo-bts/lchan.h @@ -0,0 +1,428 @@ +#pragma once + +#include <stdbool.h> +#include <stdint.h> +#include <netinet/in.h> + +#include <osmocom/core/timer.h> +#include <osmocom/core/linuxlist.h> +#include <osmocom/core/logging.h> +#include <osmocom/gsm/gsm_utils.h> +#include <osmocom/codec/codec.h> +#include <osmocom/codec/ecu.h> +#include <osmocom/gsm/lapdm.h> +#include <osmocom/gsm/sysinfo.h> +#include <osmocom/gsm/protocol/gsm_08_58.h> +#include <osmocom/gsm/gsm48_rest_octets.h> +#include <osmocom/gsm/protocol/gsm_04_08.h> +#include <osmocom/gsm/meas_rep.h> +#include <osmocom/netif/osmux.h> + +#include <osmo-bts/power_control.h> + +#define LOGPLCHAN(lchan, ss, lvl, fmt, args...) LOGP(ss, lvl, "%s " fmt, gsm_lchan_name(lchan), ## args) + +enum lchan_ciph_state { + LCHAN_CIPH_NONE, + LCHAN_CIPH_RX_REQ, + LCHAN_CIPH_RX_CONF, + LCHAN_CIPH_RXTX_REQ, + LCHAN_CIPH_RX_CONF_TX_REQ, + LCHAN_CIPH_RXTX_CONF, +}; + +/* state of a logical channel */ +enum gsm_lchan_state { + LCHAN_S_NONE, /* channel is not active */ + LCHAN_S_ACT_REQ, /* channel activation requested */ + LCHAN_S_ACTIVE, /* channel is active and operational */ + LCHAN_S_REL_REQ, /* channel release has been requested */ + LCHAN_S_REL_ERR, /* channel is in an error state */ + LCHAN_S_BROKEN, /* channel is somehow unusable */ +}; + +#define MAX_NUM_UL_MEAS 104 +#define LC_UL_M_F_L1_VALID (1 << 0) +#define LC_UL_M_F_RES_VALID (1 << 1) +#define LC_UL_M_F_OSMO_EXT_VALID (1 << 2) + +#define MAX_A5_KEY_LEN (128/8) +#define RSL_ENC_ALG_A5(x) (x+1) + +struct bts_ul_meas { + /* BER in units of 0.01%: 10.000 == 100% ber, 0 == 0% ber */ + uint16_t ber10k; + /* timing advance offset (in 1/256 bits) */ + int16_t ta_offs_256bits; + /* C/I ratio in cB */ + int16_t ci_cb; + /* flags */ + uint8_t is_sub:1; + /* RSSI in dBm * -1 */ + uint8_t inv_rssi; +}; + +struct amr_mode { + uint8_t mode; + uint8_t threshold; + uint8_t hysteresis; +}; + +struct amr_multirate_conf { + uint8_t gsm48_ie[2]; + struct amr_mode mode[4]; + uint8_t num_modes; +}; + +enum lchan_csd_mode { + LCHAN_CSD_M_NT = 0, + LCHAN_CSD_M_T_1200_75, + LCHAN_CSD_M_T_600, + LCHAN_CSD_M_T_1200, + LCHAN_CSD_M_T_2400, + LCHAN_CSD_M_T_4800, + LCHAN_CSD_M_T_9600, + LCHAN_CSD_M_T_14400, + LCHAN_CSD_M_T_29000, + LCHAN_CSD_M_T_32000, + _LCHAN_CSD_M_NUM, +}; + +/* State of the SAPIs in the lchan */ +enum lchan_sapi_state { + LCHAN_SAPI_S_NONE, + LCHAN_SAPI_S_REQ, + LCHAN_SAPI_S_ASSIGNED, + LCHAN_SAPI_S_REL, + LCHAN_SAPI_S_ERROR, +}; + +/* What kind of release/activation is done? A silent one for + * the PDCH or one triggered through RSL? */ +enum lchan_rel_act_kind { + LCHAN_REL_ACT_RSL, + LCHAN_REL_ACT_PCU, + LCHAN_REL_ACT_OML, + LCHAN_REL_ACT_REACT, /* FIXME: remove once auto-activation hack is removed from opstart_compl() (OS#1575) */ +}; + +struct gsm_rep_facch { + struct msgb *msg; + uint32_t fn; +}; + + +struct lchan_power_ctrl_state { + /* Dynamic Power Control parameters (NULL in static mode) */ + const struct gsm_power_ctrl_params *dpc_params; + /* Measurement pre-processing state (for dynamic mode) */ + struct gsm_power_ctrl_meas_proc_state rxlev_meas_proc; + struct gsm_power_ctrl_meas_proc_state rxqual_meas_proc; + struct gsm_power_ctrl_meas_proc_state ci_meas_proc; + /* Number of SACCH blocks to skip (for dynamic mode) */ + int skip_block_num; + + /* Depending on the context (MS or BS power control), fields 'current' and 'max' + * reflect either the MS power level (magic numbers), or BS Power reduction level + * (attenuation, in dB). */ + uint8_t current; + uint8_t max; +}; + +struct lchan_ta_ctrl_state { + /* Number of SACCH blocks to skip */ + int skip_block_num; + /* Currently requested TA */ + uint8_t current; +}; + +struct gsm_lchan { + /* The TS that we're part of */ + struct gsm_bts_trx_ts *ts; + /* The logical subslot number in the TS */ + uint8_t nr; + /* The logical channel type */ + enum gsm_chan_t type; + /* RSL channel rate and type */ + enum rsl_cmod_crt rsl_chan_rt; + /* RSL channel mode */ + enum rsl_cmod_spd rsl_cmode; + /* If TCH, traffic channel mode */ + enum gsm48_chan_mode tch_mode; + enum lchan_csd_mode csd_mode; + /* State */ + enum gsm_lchan_state state; + const char *broken_reason; + /* Encryption information */ + struct { + uint8_t alg_id; + uint8_t key_len; + uint8_t key[MAX_A5_KEY_LEN]; + } encr; + + struct { + uint32_t bound_ip; + uint32_t connect_ip; + uint16_t bound_port; + uint16_t connect_port; + uint16_t conn_id; + uint8_t rtp_payload; + uint8_t rtp_payload2; + uint8_t speech_mode; + struct { + bool use; + uint8_t local_cid; + uint8_t remote_cid; + /* Rx Osmux -> RTP, one allocated & owned per lchan */ + struct osmux_out_handle *out; + /* Tx RTP -> Osmux, shared by all lchans sharing a + * remote endp (addr+port), see "struct osmux_handle" */ + struct osmux_in_handle *in; + /* Used to build rtp messages we send to osmux */ + struct osmo_rtp_handle *rtpst; + } osmux; + struct osmo_rtp_socket *rtp_socket; + } abis_ip; + + char *name; + + /* For handover, activation is described in 3GPP TS 48.058 4.1.3 and 4.1.4: + * + * | | Access || transmit | activate + * | MS Power | Delay || on main channel | dl SACCH + * ---------------------------------------------------------------------- + * async ho no * --> yes no + * async ho yes * --> yes may be started + * sync ho no no --> yes no + * sync ho yes no --> yes may be started + * sync ho yes yes --> yes shall be started + * + * Always start the main channel immediately. + * want_dl_sacch_active indicates whether dl SACCH should be activated on CHAN ACT. + */ + bool want_dl_sacch_active; + + /* Number of different GsmL1_Sapi_t used in osmo_bts_sysmo is 23. + * Currently we don't share these headers so this is a magic number. */ + struct llist_head sapi_cmds; + uint8_t sapis_dl[23]; + uint8_t sapis_ul[23]; + struct lapdm_channel lapdm_ch; + /* It is required to have L3 info with DL establishment. */ + bool l3_info_estab; + struct llist_head dl_tch_queue; + unsigned int dl_tch_queue_len; + struct { + /* bitmask of all SI that are present/valid in si_buf */ + uint32_t valid; + /* bitmask of all SI that do not mirror the BTS-global SI values */ + uint32_t overridden; + uint32_t last; + /* buffers where we put the pre-computed SI: + SI2Q_MAX_NUM is the max number of SI2quater messages (see 3GPP TS 44.018) */ + sysinfo_buf_t buf[_MAX_SYSINFO_TYPE][SI2Q_MAX_NUM]; + } si; + struct { + uint8_t flags; + /* RSL measurement result number, 0 at lchan_act */ + uint8_t res_nr; + /* number of measurements stored in array below */ + uint8_t num_ul_meas; + struct bts_ul_meas uplink[MAX_NUM_UL_MEAS]; + /* last L1 header from the MS */ + struct rsl_l1_info l1_info; + struct gsm_meas_rep_unidir ul_res; + int16_t ms_toa256; + int16_t ul_ci_cb_full; + int16_t ul_ci_cb_sub; + /* Frame number of the last measurement indication receceived */ + uint32_t last_fn; + /* Osmocom extended measurement results, see LC_UL_M_F_EXTD_VALID */ + struct { + /* minimum value of toa256 during measurement period */ + int16_t toa256_min; + /* maximum value of toa256 during measurement period */ + int16_t toa256_max; + /* standard deviation of toa256 value during measurement period */ + uint16_t toa256_std_dev; + } ext; + /* Interference levels reported by PHY (in dBm) */ + int16_t interf_meas_avg_dbm; /* Average value */ + int16_t interf_meas_dbm[31]; /* Intave max is 31 */ + uint8_t interf_meas_num; + uint8_t interf_band; + } meas; + struct { + struct amr_multirate_conf amr_mr; + struct { + struct osmo_fsm_inst *dl_amr_fsm; + /* TCH cache */ + uint8_t cache[20]; + /* FACCH cache */ + uint8_t facch[GSM_MACBLOCK_LEN]; + uint8_t len; + uint32_t fn; + bool is_update; + /* set for each SID frame to detect talkspurt for codecs + without explicit ONSET event */ + bool ul_sid; + /* indicates if DTXd was active during DL measurement + period */ + bool dl_active; + /* last UL SPEECH resume flag */ + bool is_speech_resume; + } dtx; + struct { + bool last_rtp_input_was_sid; + uint8_t last_sid[GSM_FR_BYTES]; + uint8_t last_sid_len; + uint8_t last_sid_age; + /* A SID was transmitted on the DL in the period + * beginning with the last transmitted speech frame + * or the last mandatory-Tx position, whichever was + * more recent. */ + bool dl_sid_transmitted; + /* The current frame in the DL is taken up by FACCH */ + bool dl_facch_stealing; + } dtx_fr_hr_efr; + uint8_t last_cmr; + uint32_t last_fn; + struct { + /* buffers to re-combine RLP frame from multiple Um blocks */ + uint8_t rlp_buf_ul[576/8]; /* maximum size of RLP frame */ + uint8_t rlp_buf_dl[576/8]; /* maximum size of RLP frame */ + } csd; + } tch; + + /* 3GPP TS 48.058 ยง 9.3.37: [0; 255] ok, -1 means invalid*/ + int16_t ms_t_offs; + /* 3GPP TS 45.010 ยง 1.2 round trip propagation delay (in symbols) or -1 */ + int16_t p_offs; + + /* BTS-side ciphering state (rx only, bi-directional, ...) */ + uint8_t ciph_state; + uint8_t ciph_ns; + uint8_t loopback; + struct { + uint8_t active; + uint8_t ref; + /* T3105: PHYS INF retransmission */ + struct osmo_timer_list t3105; + /* counts up to Ny1 */ + unsigned int phys_info_count; + } ho; + struct { + bool listener_detected; + uint8_t talker_active; + uint8_t ref; + uint32_t fn; + /* T3115: VGCS UPLINK GRANT retransmission */ + struct osmo_timer_list t3115; + /* counts up to Ny2 */ + unsigned int vgcs_ul_grant_count; + /* uplink free message */ + bool uplink_free; + uint8_t uplink_free_msg[GSM_MACBLOCK_LEN]; + } asci; + /* S counter for link loss */ + int s; + /* Kind of the release/activation. E.g. RSL or PCU */ + enum lchan_rel_act_kind rel_act_kind; + /* Pending RSL CHANnel ACTIVation message */ + struct msgb *pending_chan_activ; + /* RTP header Marker bit to indicate beginning of speech after pause */ + bool rtp_tx_marker; + + /* TA Control Loop */ + struct lchan_ta_ctrl_state ta_ctrl; + + /* MS/BS power control state */ + struct lchan_power_ctrl_state ms_power_ctrl; + struct lchan_power_ctrl_state bs_power_ctrl; + + /* MS/BS Dynamic Power Control parameters */ + struct gsm_power_ctrl_params ms_dpc_params; + struct gsm_power_ctrl_params bs_dpc_params; + + /* Temporary ACCH overpower capabilities and state */ + struct abis_rsl_osmo_temp_ovp_acch_cap top_acch_cap; + bool top_acch_active; + + struct msgb *pending_rel_ind_msg; + + /* ECU (Error Concealment Unit) state */ + struct osmo_ecu_state *ecu_state; + + /* Repeated ACCH capabilities and current state */ + struct abis_rsl_osmo_rep_acch_cap rep_acch_cap; + struct { + bool dl_facch_active; + bool ul_sacch_active; + bool dl_sacch_active; + + /* Message buffers to store repeation candidates */ + struct gsm_rep_facch dl_facch[2]; + struct msgb *dl_sacch_msg; + } rep_acch; + + /* Cached early Immediate Assignment message: if the Immediate Assignment arrives before the channel is + * confirmed active, then cache it here and send it once the channel is confirmed to be active. This is related + * to the Early IA feature, see OsmoBSC config option 'immediate-assignment pre-chan-ack'. */ + struct msgb *early_rr_ia; + struct osmo_timer_list early_rr_ia_delay; +}; + +extern const struct value_string lchan_ciph_state_names[]; +static inline const char *lchan_ciph_state_name(uint8_t state) +{ + return get_value_string(lchan_ciph_state_names, state); +} + +#define GSM_LCHAN_SI(lchan, i) (void *)((lchan)->si.buf[i][0]) + +void gsm_lchan_init(struct gsm_lchan *lchan, struct gsm_bts_trx_ts *ts, unsigned int lchan_nr); +void gsm_lchan_name_update(struct gsm_lchan *lchan); +int lchan_init_lapdm(struct gsm_lchan *lchan); +void gsm_lchan_release(struct gsm_lchan *lchan, enum lchan_rel_act_kind rel_kind); +int lchan_deactivate(struct gsm_lchan *lchan); +const char *gsm_lchans_name(enum gsm_lchan_state s); + +static inline char *gsm_lchan_name(const struct gsm_lchan *lchan) +{ + return lchan->name; +} + +uint8_t *lchan_sacch_get(struct gsm_lchan *lchan); + +uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan); +uint8_t gsm_lchan2chan_nr_rsl(const struct gsm_lchan *lchan); +uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan, + enum gsm_phys_chan_config as_pchan); + +void gsm_lchan_interf_meas_push(struct gsm_lchan *lchan, int dbm); +void gsm_lchan_interf_meas_calc_avg(struct gsm_lchan *lchan); + +int lchan2ecu_codec(const struct gsm_lchan *lchan); + +void lchan_set_state(struct gsm_lchan *lchan, enum gsm_lchan_state state); + +int lchan_rtp_socket_create(struct gsm_lchan *lchan, const char *bind_ip); +int lchan_rtp_socket_connect(struct gsm_lchan *lchan, const struct in_addr *ia, uint16_t connect_port); +void lchan_rtp_socket_free(struct gsm_lchan *lchan); + +void lchan_dl_tch_queue_enqueue(struct gsm_lchan *lchan, struct msgb *msg, unsigned int limit); + +static inline bool lchan_is_dcch(const struct gsm_lchan *lchan) +{ + switch (lchan->type) { + case GSM_LCHAN_SDCCH: + case GSM_LCHAN_TCH_F: + case GSM_LCHAN_TCH_H: + return true; + default: + return false; + } +} + +#define lchan_is_tch(lchan) \ + ((lchan)->type == GSM_LCHAN_TCH_F || (lchan)->type == GSM_LCHAN_TCH_H) diff --git a/include/osmo-bts/logging.h b/include/osmo-bts/logging.h index 852c3836..ce08e47c 100644 --- a/include/osmo-bts/logging.h +++ b/include/osmo-bts/logging.h @@ -20,7 +20,8 @@ enum { DLOOP, DABIS, DRTP, - DSUM, + DOSMUX, + DASCI, }; extern const struct log_info bts_log_info; @@ -37,4 +38,12 @@ extern const struct log_info bts_log_info; #define DEBUGPFN(ss, fn, fmt, args...) \ LOGP(ss, LOGL_DEBUG, "%s " fmt, gsm_fn_as_gsmtime_str(fn), ## args) +/* LOGP with lchan + frame number prefix */ +#define LOGPLCFN(lchan, fn, ss, lvl, fmt, args...) \ + LOGP(ss, lvl, "%s %s " fmt, gsm_lchan_name(lchan), gsm_fn_as_gsmtime_str(fn), ## args) + +/* LOGP with lchan + gsm_time prefix */ +#define LOGPLCGT(lchan, gt, ss, lvl, fmt, args...) \ + LOGP(ss, lvl, "%s %s " fmt, gsm_lchan_name(lchan), osmo_dump_gsmtime(gt), ## args) + #endif /* _LOGGING_H */ diff --git a/include/osmo-bts/measurement.h b/include/osmo-bts/measurement.h index 45f275f1..ad86d8de 100644 --- a/include/osmo-bts/measurement.h +++ b/include/osmo-bts/measurement.h @@ -20,4 +20,6 @@ bool ts45008_83_is_sub(struct gsm_lchan *lchan, uint32_t fn); int is_meas_complete(struct gsm_lchan *lchan, uint32_t fn); +void lchan_meas_handle_sacch(struct gsm_lchan *lchan, struct msgb *msg); + #endif diff --git a/include/osmo-bts/msg_utils.h b/include/osmo-bts/msg_utils.h index 7ddbe88f..fb8e11a5 100644 --- a/include/osmo-bts/msg_utils.h +++ b/include/osmo-bts/msg_utils.h @@ -22,6 +22,9 @@ struct msgb; /* Access 3rd part of msgb control buffer */ #define rtpmsg_ts(x) ((x)->cb[2]) +/* Access 4th part of msgb control buffer */ +#define rtpmsg_is_rfc5993_sid(x) ((x)->cb[3]) + /** * Classification of OML message. ETSI for plain GSM 12.21 * messages and IPA/Osmo for manufacturer messages. diff --git a/include/osmo-bts/nm_common_fsm.h b/include/osmo-bts/nm_common_fsm.h index 4679b235..dadf806e 100644 --- a/include/osmo-bts/nm_common_fsm.h +++ b/include/osmo-bts/nm_common_fsm.h @@ -1,7 +1,7 @@ /* Header for all NM FSM. Following 3GPP TS 12.21 Figure 2/GSM 12.21: GSM 12.21 Objects' Operational state and availability status behaviour during initialization */ -/* (C) 2020 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> +/* (C) 2020 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * Author: Pau Espin Pedrol <pespin@sysmocom.de> * * All Rights Reserved @@ -14,7 +14,7 @@ * 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 General Public License for more details. + * 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/>. @@ -25,18 +25,23 @@ #include <osmocom/core/fsm.h> #include <osmocom/core/utils.h> +#include <osmocom/core/msgb.h> /* Common */ enum nm_fsm_events { NM_EV_SW_ACT, + NM_EV_RX_SETATTR, /* data: struct nm_fsm_ev_setattr_data */ + NM_EV_RX_OPSTART, NM_EV_OPSTART_ACK, NM_EV_OPSTART_NACK, + NM_EV_SHUTDOWN_START, + NM_EV_SHUTDOWN_FINISH, + NM_EV_OML_UP, NM_EV_RSL_UP, /* RadioCarrier and BaseBand Transceiver only */ NM_EV_RSL_DOWN, /* RadioCarrier and BaseBand Transceiver only */ NM_EV_PHYLINK_UP, /* RadioCarrier and BaseBand Transceiver only */ NM_EV_PHYLINK_DOWN, /* RadioCarrier and BaseBand Transceiver only */ NM_EV_DISABLE, /* RadioCarrier and BaseBand Transceiver only */ - NM_EV_BBTRANSC_INSTALLED, /* Radio Channel only */ NM_EV_BBTRANSC_ENABLED, /* Radio Channel only */ NM_EV_BBTRANSC_DISABLED, /* Radio Channel only */ NM_EV_RCARRIER_ENABLED, /* Radio Channel only */ @@ -44,6 +49,10 @@ enum nm_fsm_events { }; extern const struct value_string nm_fsm_event_names[]; +struct nm_fsm_ev_setattr_data { + const struct msgb *msg; +}; + /* BTS SiteManager */ enum nm_bts_sm_op_fsm_states { @@ -85,3 +94,30 @@ enum nm_chan_op_fsm_states { NM_CHAN_ST_OP_ENABLED, }; extern struct osmo_fsm nm_chan_fsm; + +/* GPRS NSE */ +enum nm_gprs_nse_op_fsm_states { + NM_GPRS_NSE_ST_OP_DISABLED_NOTINSTALLED, + NM_GPRS_NSE_ST_OP_DISABLED_DEPENDENCY, + NM_GPRS_NSE_ST_OP_DISABLED_OFFLINE, + NM_GPRS_NSE_ST_OP_ENABLED, +}; +extern struct osmo_fsm nm_gprs_nse_fsm; + +/* GPRS NSVC */ +enum nm_gprs_nsvc_op_fsm_states { + NM_GPRS_NSVC_ST_OP_DISABLED_NOTINSTALLED, + NM_GPRS_NSVC_ST_OP_DISABLED_DEPENDENCY, + NM_GPRS_NSVC_ST_OP_DISABLED_OFFLINE, + NM_GPRS_NSVC_ST_OP_ENABLED, +}; +extern struct osmo_fsm nm_gprs_nsvc_fsm; + +/* GPRS CELL */ +enum nm_gprs_cell_op_fsm_states { + NM_GPRS_CELL_ST_OP_DISABLED_NOTINSTALLED, + NM_GPRS_CELL_ST_OP_DISABLED_DEPENDENCY, + NM_GPRS_CELL_ST_OP_DISABLED_OFFLINE, + NM_GPRS_CELL_ST_OP_ENABLED, +}; +extern struct osmo_fsm nm_gprs_cell_fsm; diff --git a/include/osmo-bts/notification.h b/include/osmo-bts/notification.h new file mode 100644 index 00000000..e53d718b --- /dev/null +++ b/include/osmo-bts/notification.h @@ -0,0 +1,61 @@ +/* Maintain and generate ASCI notifications */ + +/* + * (C) 2023 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * SPDX-License-Identifier: AGPL-3.0+ + * + * Author: Harald Welte + * + * 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/>. + */ + +#pragma once + +/* one [concurrent] ASCI (VBS/VGCS) notification */ +struct asci_notification { + struct llist_head list; /* linked to bts->asci.notifications */ + + /* Group call reference (TS 24.008 10.5.1.9 "Descriptive group or broadcast call reference") */ + uint8_t group_call_ref[5]; + + /* Group Channel Description (TS 44.018 10.5.2.14b) */ + struct { + bool present; + uint8_t value[255]; + uint8_t len; + } chan_desc; + + /* NCH DRX Information (TS 48.058 9.3.47) */ + struct { + bool present; + struct rsl_ie_nch_drx_info value; + } nch_drx_info; +}; + +int bts_asci_notification_add(struct gsm_bts *bts, const uint8_t *group_call_ref, const uint8_t *chan_desc, + uint8_t chan_desc_len, const struct rsl_ie_nch_drx_info *nch_drx_info); + +int bts_asci_notification_del(struct gsm_bts *bts, const uint8_t *group_call_ref); + +int bts_asci_notification_reset(struct gsm_bts *bts); + +const struct asci_notification *bts_asci_notification_get_next(struct gsm_bts *bts); + +void append_group_call_information(struct bitvec *bv, const uint8_t *gcr, const uint8_t *ch_desc, uint8_t ch_desc_len); + +int bts_asci_notify_nch_gen_msg(struct gsm_bts *bts, uint8_t *out_buf); +int bts_asci_notify_facch_gen_msg(struct gsm_bts *bts, uint8_t *out_buf, const uint8_t *group_call_ref, + const uint8_t *chan_desc, uint8_t chan_desc_len); diff --git a/include/osmo-bts/oml.h b/include/osmo-bts/oml.h index 27afc538..41cdaf50 100644 --- a/include/osmo-bts/oml.h +++ b/include/osmo-bts/oml.h @@ -32,6 +32,7 @@ struct gsm_abis_mo { struct gsm_bts *bts; /* NM BTS Site Manager FSM */ struct osmo_fsm_inst *fi; + bool setattr_success; bool opstart_success; }; @@ -47,7 +48,7 @@ int oml_mo_statechg_ack(const struct gsm_abis_mo *mo); int oml_mo_statechg_nack(const struct gsm_abis_mo *mo, uint8_t nack_cause); /* Change the state and send STATE CHG REP */ -int oml_mo_state_chg(struct gsm_abis_mo *mo, int op_state, int avail_state); +int oml_mo_state_chg(struct gsm_abis_mo *mo, int op_state, int avail_state, int adm_state); /* First initialization of MO, does _not_ generate state changes */ void oml_mo_state_init(struct gsm_abis_mo *mo, int op_state, int avail_state); @@ -62,11 +63,12 @@ int oml_tx_state_changed(const struct gsm_abis_mo *mo); int oml_mo_tx_sw_act_rep(const struct gsm_abis_mo *mo); int oml_fom_ack_nack(struct msgb *old_msg, uint8_t cause); +int oml_fom_ack_nack_copy_msg(const struct msgb *old_msg, uint8_t cause); int oml_mo_fom_ack_nack(const struct gsm_abis_mo *mo, uint8_t orig_msg_type, uint8_t cause); -extern const unsigned int oml_default_t200_ms[7]; +extern const uint32_t oml_default_t200_fn[7]; /* Transmit failure event report */ int oml_tx_failure_event_rep(const struct gsm_abis_mo *mo, enum abis_nm_severity severity, @@ -76,11 +78,11 @@ void gsm_mo_init(struct gsm_abis_mo *mo, struct gsm_bts *bts, uint8_t obj_class, uint8_t p1, uint8_t p2, uint8_t p3); struct gsm_abis_mo *gsm_objclass2mo(struct gsm_bts *bts, uint8_t obj_class, - const struct abis_om_obj_inst *obj_inst); + const struct abis_om_obj_inst *obj_inst, + enum abis_nm_nack_cause *c); -struct gsm_nm_state *gsm_objclass2nmstate(struct gsm_bts *bts, uint8_t obj_class, - const struct abis_om_obj_inst *obj_inst); void *gsm_objclass2obj(struct gsm_bts *bts, uint8_t obj_class, - const struct abis_om_obj_inst *obj_inst); + const struct abis_om_obj_inst *obj_inst, + enum abis_nm_nack_cause *c); #endif // _OML_H */ diff --git a/include/osmo-bts/osmux.h b/include/osmo-bts/osmux.h new file mode 100644 index 00000000..9cdbea19 --- /dev/null +++ b/include/osmo-bts/osmux.h @@ -0,0 +1,48 @@ +#pragma once + +#include <stdint.h> +#include <stdbool.h> +#include <osmocom/core/select.h> +#include <osmocom/netif/osmux.h> + +struct gsm_bts; +struct gsm_lchan; + +enum osmux_usage { + OSMUX_USAGE_OFF = 0, + OSMUX_USAGE_ON = 1, + OSMUX_USAGE_ONLY = 2, +}; + +struct osmux_state { + enum osmux_usage use; + char *local_addr; + uint16_t local_port; + struct osmo_fd fd; + uint8_t batch_factor; + unsigned int batch_size; + bool dummy_padding; + struct llist_head osmux_handle_list; +}; + +/* Contains a "struct osmux_in_handle" towards a specific peer (remote IPaddr+port) */ +struct osmux_handle { + struct llist_head head; + struct gsm_bts *bts; + struct osmux_in_handle *in; + struct osmo_sockaddr rem_addr; + int refcnt; +}; + +int bts_osmux_init(struct gsm_bts *bts); +void bts_osmux_release(struct gsm_bts *bts); +int bts_osmux_open(struct gsm_bts *bts); + +int lchan_osmux_init(struct gsm_lchan *lchan, uint8_t rtp_payload); +void lchan_osmux_release(struct gsm_lchan *lchan); +int lchan_osmux_connect(struct gsm_lchan *lchan); +bool lchan_osmux_connected(const struct gsm_lchan *lchan); +int lchan_osmux_send_frame(struct gsm_lchan *lchan, const uint8_t *payload, + unsigned int payload_len, unsigned int duration, bool marker); + +int lchan_osmux_skipped_frame(struct gsm_lchan *lchan, unsigned int duration); diff --git a/include/osmo-bts/paging.h b/include/osmo-bts/paging.h index ef1fc93d..e74ba3c9 100644 --- a/include/osmo-bts/paging.h +++ b/include/osmo-bts/paging.h @@ -7,6 +7,55 @@ struct paging_state; struct gsm_bts; +struct asci_notification; + +/* abstract representation of P1 rest octets; we only implement those parts we need for now */ +struct p1_rest_octets { + struct { + bool present; + uint8_t nln; + uint8_t nln_status; + } nln_pch; + bool packet_page_ind[2]; + bool r8_present; + struct { + bool prio_ul_access; + bool etws_present; + struct { + bool is_first; + uint8_t page_nr; + const uint8_t *page; + size_t page_bytes; + } etws; + } r8; +}; + +/* abstract representation of P2 rest octets; we only implement those parts we need for now */ +struct p2_rest_octets { + struct { + bool present; + uint8_t cn3; + } cneed; + struct { + bool present; + uint8_t nln; + uint8_t nln_status; + } nln_pch; +}; + +/* abstract representation of P3 rest octets; we only implement those parts we need for now */ +struct p3_rest_octets { + struct { + bool present; + uint8_t cn3; + uint8_t cn4; + } cneed; + struct { + bool present; + uint8_t nln; + uint8_t nln_status; + } nln_pch; +}; /* initialize paging code */ struct paging_state *paging_init(struct gsm_bts *bts, @@ -35,9 +84,15 @@ int paging_si_update(struct paging_state *ps, struct gsm48_control_channel_descr int paging_add_identity(struct paging_state *ps, uint8_t paging_group, const uint8_t *identity_lv, uint8_t chan_needed); -/* Add an IMM.ASS message to the paging queue */ -int paging_add_imm_ass(struct paging_state *ps, const uint8_t *data, - uint8_t len, bool from_pcu); +/* Add a ready formatted MAC block message to the paging queue, this can be an IMMEDIATE ASSIGNMENT, or a + * PAGING COMMAND (from the PCU) */ +int paging_add_macblock(struct paging_state *ps, uint32_t msg_id, const char *imsi, bool confirm, const uint8_t *macblock); + +/* Paging rest octests */ +void append_p1_rest_octets(struct bitvec *bv, const struct p1_rest_octets *p1ro, + const struct asci_notification *notif); +void append_p2_rest_octets(struct bitvec *bv, const struct p2_rest_octets *p2ro); +void append_p3_rest_octets(struct bitvec *bv, const struct p3_rest_octets *p3ro); /* generate paging message for given gsm time */ int paging_gen_msg(struct paging_state *ps, uint8_t *out_buf, struct gsm_time *gt, diff --git a/include/osmo-bts/pcu_if.h b/include/osmo-bts/pcu_if.h index 12a8abc9..3563c5ba 100644 --- a/include/osmo-bts/pcu_if.h +++ b/include/osmo-bts/pcu_if.h @@ -3,9 +3,11 @@ #include <osmo-bts/pcuif_proto.h> +struct gsm_bts_sm; + extern int pcu_direct; -#define PCUIF_HDR_SIZE ( sizeof(struct gsm_pcu_if) - sizeof(((struct gsm_pcu_if *)0)->u) ) +#define PCUIF_HDR_SIZE (sizeof(struct gsm_pcu_if) - sizeof(((struct gsm_pcu_if *)0)->u)) int pcu_tx_info_ind(void); int pcu_tx_si(const struct gsm_bts *bts, enum osmo_sysinfo_type si_type, bool enable); @@ -19,14 +21,13 @@ int pcu_tx_rach_ind(uint8_t bts_nr, uint8_t trx_nr, uint8_t ts_nr, int16_t qta, uint16_t ra, uint32_t fn, uint8_t is_11bit, enum ph_burst_type burst_type, uint8_t sapi); int pcu_tx_time_ind(uint32_t fn); -int pcu_tx_interf_ind(uint8_t bts_nr, uint8_t trx_nr, uint32_t fn, - const uint8_t *pdch_interf); +int pcu_tx_interf_ind(const struct gsm_bts_trx *trx, uint32_t fn); int pcu_tx_pag_req(const uint8_t *identity_lv, uint8_t chan_needed); -int pcu_tx_pch_data_cnf(uint32_t fn, uint8_t *data, uint8_t len); +int pcu_tx_data_cnf(uint32_t msg_id, uint8_t sapi); int pcu_tx_susp_req(struct gsm_lchan *lchan, uint32_t tlli, const uint8_t *ra_id, uint8_t cause); -int pcu_sock_send(struct gsm_network *net, struct msgb *msg); +int pcu_sock_send(struct msgb *msg); -int pcu_sock_init(const char *path); +int pcu_sock_init(const char *path, int qlength_max); void pcu_sock_exit(void); bool pcu_connected(void); diff --git a/include/osmo-bts/pcuif_proto.h b/include/osmo-bts/pcuif_proto.h index 3e6f6510..04936af0 100644 --- a/include/osmo-bts/pcuif_proto.h +++ b/include/osmo-bts/pcuif_proto.h @@ -3,20 +3,20 @@ #include <osmocom/gsm/l1sap.h> #include <arpa/inet.h> +#include <osmocom/gsm/protocol/gsm_23_003.h> #define PCU_SOCK_DEFAULT "/tmp/pcu_bts" -#define PCU_IF_VERSION 0x0a +#define PCU_IF_VERSION 0x0c #define TXT_MAX_LEN 128 /* msg_type */ #define PCU_IF_MSG_DATA_REQ 0x00 /* send data to given channel */ -#define PCU_IF_MSG_DATA_CNF 0x01 /* confirm (e.g. transmission on PCH) */ #define PCU_IF_MSG_DATA_IND 0x02 /* receive data from given channel */ #define PCU_IF_MSG_SUSP_REQ 0x03 /* BTS forwards GPRS SUSP REQ to PCU */ #define PCU_IF_MSG_APP_INFO_REQ 0x04 /* BTS asks PCU to transmit APP INFO via PACCH */ #define PCU_IF_MSG_RTS_REQ 0x10 /* ready to send request */ -#define PCU_IF_MSG_DATA_CNF_DT 0x11 /* confirm (with direct tlli) */ +#define PCU_IF_MSG_DATA_CNF_2 0x11 /* confirm (using message id) */ #define PCU_IF_MSG_RACH_IND 0x22 /* receive RACH */ #define PCU_IF_MSG_INFO_IND 0x32 /* retrieve BTS info */ #define PCU_IF_MSG_ACT_REQ 0x40 /* activate/deactivate PDCH */ @@ -28,17 +28,16 @@ /* sapi */ #define PCU_IF_SAPI_RACH 0x01 /* channel request on CCCH */ -#define PCU_IF_SAPI_AGCH 0x02 /* assignment on AGCH */ -#define PCU_IF_SAPI_PCH 0x03 /* paging/assignment on PCH */ #define PCU_IF_SAPI_BCCH 0x04 /* SI on BCCH */ #define PCU_IF_SAPI_PDTCH 0x05 /* packet data/control/ccch block */ #define PCU_IF_SAPI_PRACH 0x06 /* packet random access channel */ #define PCU_IF_SAPI_PTCCH 0x07 /* packet TA control channel */ -#define PCU_IF_SAPI_AGCH_DT 0x08 /* assignment on AGCH but with additional TLLI */ +#define PCU_IF_SAPI_PCH_2 0x08 /* assignment on PCH (confirmed using message id) */ +#define PCU_IF_SAPI_AGCH_2 0x09 /* assignment on AGCH (confirmed using message id) */ /* flags */ #define PCU_IF_FLAG_ACTIVE (1 << 0)/* BTS is active */ -#define PCU_IF_FLAG_SYSMO (1 << 1)/* access PDCH of sysmoBTS directly */ +#define PCU_IF_FLAG_DIRECT_PHY (1 << 1)/* access PHY directly via dedicated hardware support */ #define PCU_IF_FLAG_CS1 (1 << 16) #define PCU_IF_FLAG_CS2 (1 << 17) #define PCU_IF_FLAG_CS3 (1 << 18) @@ -58,6 +57,20 @@ #define PCU_IF_ADDR_TYPE_IPV4 0x04 /* IPv4 address */ #define PCU_IF_ADDR_TYPE_IPV6 0x29 /* IPv6 address */ +/* BTS model */ +enum gsm_pcuif_bts_model { + PCU_IF_BTS_MODEL_UNSPEC, + PCU_IF_BTS_MODEL_LC15, + PCU_IF_BTS_MODEL_OC2G, + PCU_IF_BTS_MODEL_OCTPHY, + PCU_IF_BTS_MODEL_SYSMO, + PCU_IF_BTS_MODEL_TRX, + PCU_IF_BTS_MODEL_RBS, +}; + +#define PCU_IF_NUM_NSVC 2 +#define PCU_IF_NUM_TRX 8 + enum gsm_pcu_if_text_type { PCU_VERSION, PCU_OML_ALERT, @@ -83,19 +96,10 @@ struct gsm_pcu_if_data { int16_t lqual_cb; /* !< \brief Link quality in centiBel */ } __attribute__ ((packed)); -/* data confirmation with direct tlli (instead of raw mac block with tlli) */ -struct gsm_pcu_if_data_cnf_dt { +/* data confirmation with message id (instead of raw mac block) */ +struct gsm_pcu_if_data_cnf { uint8_t sapi; - uint32_t tlli; - uint32_t fn; - uint16_t arfcn; - uint8_t trx_nr; - uint8_t ts_nr; - uint8_t block_nr; - int8_t rssi; - uint16_t ber10k; /* !< \brief BER in units of 0.01% */ - int16_t ta_offs_qbits; /* !< \brief Burst TA Offset in quarter bits */ - int16_t lqual_cb; /* !< \brief Link quality in centiBel */ + uint32_t msg_id; } __attribute__ ((packed)); struct gsm_pcu_if_rts_req { @@ -140,7 +144,7 @@ struct gsm_pcu_if_info_trx { struct gsm_pcu_if_info_ind { uint32_t version; uint32_t flags; - struct gsm_pcu_if_info_trx trx[8]; /* TRX infos per BTS */ + struct gsm_pcu_if_info_trx trx[PCU_IF_NUM_TRX]; /* TRX infos per BTS */ uint8_t bsic; /* RAI */ uint16_t mcc, mnc; @@ -169,14 +173,15 @@ struct gsm_pcu_if_info_ind { uint8_t initial_cs; uint8_t initial_mcs; /* NSVC */ - uint16_t nsvci[2]; - uint16_t local_port[2]; - uint16_t remote_port[2]; - uint8_t address_type[2]; + uint16_t nsvci[PCU_IF_NUM_NSVC]; + uint16_t local_port[PCU_IF_NUM_NSVC]; + uint16_t remote_port[PCU_IF_NUM_NSVC]; + uint8_t address_type[PCU_IF_NUM_NSVC]; union { struct in_addr v4; struct in6_addr v6; - } remote_ip[2]; + } remote_ip[PCU_IF_NUM_NSVC]; + uint8_t bts_model; /* enum gsm_pcuif_bts_model */ } __attribute__ ((packed)); struct gsm_pcu_if_act_req { @@ -226,6 +231,32 @@ struct gsm_pcu_if_container { uint8_t data[0]; } __attribute__ ((packed)); +/* Struct to send a (confirmed) IMMEDIATE ASSIGNMENT message via PCH. The struct is sent as a data request + * (data_req) under SAPI PCU_IF_SAPI_PCH_2. */ +struct gsm_pcu_if_pch { + /* message id as reference for confirmation */ + uint32_t msg_id; + /* IMSI (to derive paging group) */ + char imsi[OSMO_IMSI_BUF_SIZE]; + /* GSM mac-block (with immediate assignment message) */ + uint8_t data[GSM_MACBLOCK_LEN]; + /* Set to true in case the receiving end must send a confirmation + * when the MAC block (data) has been sent. */ + bool confirm; +} __attribute__((packed)); + +/* Struct to send a (confirmed) IMMEDIATE ASSIGNMENT message via AGCH. The struct is sent as a data request + * (data_req) under SAPI PCU_IF_SAPI_AGCH_2. */ +struct gsm_pcu_if_agch { + /* message id as reference for confirmation */ + uint32_t msg_id; + /* GSM mac-block (with immediate assignment message) */ + uint8_t data[GSM_MACBLOCK_LEN]; + /* Set to true in case the receiving end must send a confirmation + * when the MAC block (data) has been sent. */ + bool confirm; +} __attribute__((packed)); + struct gsm_pcu_if { /* context based information */ uint8_t msg_type; /* message type */ @@ -234,8 +265,7 @@ struct gsm_pcu_if { union { struct gsm_pcu_if_data data_req; - struct gsm_pcu_if_data data_cnf; - struct gsm_pcu_if_data_cnf_dt data_cnf_dt; + struct gsm_pcu_if_data_cnf data_cnf2; struct gsm_pcu_if_data data_ind; struct gsm_pcu_if_susp_req susp_req; struct gsm_pcu_if_rts_req rts_req; diff --git a/include/osmo-bts/phy_link.h b/include/osmo-bts/phy_link.h index 4b8a8633..862ed48f 100644 --- a/include/osmo-bts/phy_link.h +++ b/include/osmo-bts/phy_link.h @@ -50,7 +50,8 @@ struct phy_link { bool use_legacy_setbsic; uint8_t trxd_pdu_ver_max; /* Maximum TRXD PDU version to negotiate */ bool powered; /* last POWERON (true) or POWEROFF (false) confirmed */ - bool poweronoff_sent; /* is there a POWERON/POWEROFF in transit? (one or the other based on ->powered) */ + bool poweron_sent; /* is there a POWERON in transit? */ + bool poweroff_sent; /* is there a POWEROFF in transit? */ } osmotrx; struct { char *mcast_dev; /* Network device for multicast */ @@ -112,7 +113,6 @@ struct phy_instance { } sysmobts; struct { struct trx_l1h *hdl; - bool sw_act_reported; struct trx_dl_burst_req br[TRX_NR_TS]; } osmotrx; struct { @@ -175,6 +175,7 @@ static inline struct phy_instance *trx_phy_instance(const struct gsm_bts_trx *tr } int bts_model_phy_link_open(struct phy_link *plink); +int bts_model_phy_link_close(struct phy_link *plink); #define LOGPPHL(plink, section, lvl, fmt, args...) LOGP(section, lvl, "%s: " fmt, phy_link_name(plink), ##args) #define LOGPPHI(pinst, section, lvl, fmt, args...) LOGP(section, lvl, "%s: " fmt, phy_instance_name(pinst), ##args) diff --git a/include/osmo-bts/power_control.h b/include/osmo-bts/power_control.h index f2e14cfe..0764ba76 100644 --- a/include/osmo-bts/power_control.h +++ b/include/osmo-bts/power_control.h @@ -1,11 +1,90 @@ #pragma once #include <stdint.h> -#include <osmo-bts/gsm_data.h> +#include <stdbool.h> +/* MS/BS Power related measurement averaging algo */ +enum gsm_power_ctrl_meas_avg_algo { + GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE = 0x00, + GSM_PWR_CTRL_MEAS_AVG_ALGO_UNWEIGHTED = 0x01, + GSM_PWR_CTRL_MEAS_AVG_ALGO_WEIGHTED = 0x02, + GSM_PWR_CTRL_MEAS_AVG_ALGO_MOD_MEDIAN = 0x03, + /* EWMA is an Osmocom specific algo */ + GSM_PWR_CTRL_MEAS_AVG_ALGO_OSMO_EWMA = 0x04, +}; + +/* MS/BS Power related measurement parameters */ +struct gsm_power_ctrl_meas_params { + /* Thresholds (see 3GPP TS 45.008, section A.3.2.1) */ + uint8_t lower_thresh; /* lower (decreasing) direction */ + uint8_t upper_thresh; /* upper (increasing) direction */ + + /* Threshold Comparators for lower (decreasing) direction */ + uint8_t lower_cmp_p; /* P1 for RxLev, P3 for RxQual */ + uint8_t lower_cmp_n; /* N1 for RxLev, N3 for RxQual */ + /* Threshold Comparators for upper (increasing) direction */ + uint8_t upper_cmp_p; /* P2 for RxLev, P4 for RxQual */ + uint8_t upper_cmp_n; /* N2 for RxLev, N4 for RxQual */ + + /* Hreqave and Hreqt (see 3GPP TS 45.008, Annex A) */ + uint8_t h_reqave; + uint8_t h_reqt; + + /* AVG algorithm and its specific parameters */ + enum gsm_power_ctrl_meas_avg_algo algo; + union { + /* Exponentially Weighted Moving Average */ + struct { + /* Smoothing factor: higher the value - less smoothing */ + uint8_t alpha; /* 1 .. 99 (in %) */ + } ewma; + }; +}; + +/* MS/BS Power Control parameters */ +struct gsm_power_ctrl_params { + /* Minimum interval between power level changes */ + uint8_t ctrl_interval; /* 1 step is 2 SACCH periods */ + + /* Power change step size (maximum) */ + uint8_t inc_step_size_db; /* increasing direction */ + uint8_t red_step_size_db; /* reducing direction */ + + /* Measurement averaging parameters for RxLev & RxQual */ + struct gsm_power_ctrl_meas_params rxqual_meas; + struct gsm_power_ctrl_meas_params rxlev_meas; + + /* Measurement averaging parameters for C/I, per chan type */ + struct gsm_power_ctrl_meas_params ci_fr_meas; + struct gsm_power_ctrl_meas_params ci_hr_meas; + struct gsm_power_ctrl_meas_params ci_amr_fr_meas; + struct gsm_power_ctrl_meas_params ci_amr_hr_meas; + struct gsm_power_ctrl_meas_params ci_sdcch_meas; + struct gsm_power_ctrl_meas_params ci_gprs_meas; +}; + +/* Measurement pre-processing state */ +struct gsm_power_ctrl_meas_proc_state { + /* Number of measurements processed */ + unsigned int meas_num; + /* Algorithm specific data */ + union { + struct { + /* Scaled up 100 times average value */ + int Avg100; + } ewma; + }; +}; + +/* Default MS/BS Power Control parameters */ +extern const struct gsm_power_ctrl_params power_ctrl_params_def; +void power_ctrl_params_def_reset(struct gsm_power_ctrl_params *params, bool is_bs_pwr); + +struct gsm_lchan; int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan, const uint8_t ms_power_lvl, - const int8_t ul_rssi_dbm); + const int8_t ul_rssi_dbm, + const int16_t ul_lqual_cb); int lchan_bs_pwr_ctrl(struct gsm_lchan *lchan, - const struct gsm48_hdr *gh); + const struct gsm48_meas_res *mr); diff --git a/include/osmo-bts/rsl.h b/include/osmo-bts/rsl.h index 4e79de5e..e3950e42 100644 --- a/include/osmo-bts/rsl.h +++ b/include/osmo-bts/rsl.h @@ -4,7 +4,8 @@ #define LCHAN_FN_DUMMY 0xFFFFFFFF #define LCHAN_FN_WAIT 0xFFFFFFFE -int msgb_queue_flush(struct llist_head *list); +bool rsl_chan_rt_is_asci(enum rsl_cmod_crt chan_rt); +bool rsl_chan_rt_is_vgcs(enum rsl_cmod_crt chan_rt); int down_rsl(struct gsm_bts_trx *trx, struct msgb *msg); int rsl_tx_rf_res(struct gsm_bts_trx *trx); @@ -16,8 +17,8 @@ int rsl_tx_chan_act_acknack(struct gsm_lchan *lchan, uint8_t cause); int rsl_tx_conn_fail(const struct gsm_lchan *lchan, uint8_t cause); int rsl_tx_rf_rel_ack(struct gsm_lchan *lchan); int rsl_tx_hando_det(struct gsm_lchan *lchan, uint8_t *ho_delay); - -int lchan_deactivate(struct gsm_lchan *lchan); +int rsl_tx_listener_det(struct gsm_lchan *lchan, uint8_t *acc_delay); +int rsl_tx_talker_det(struct gsm_lchan *lchan, uint8_t *acc_delay); /* call-back for LAPDm code, called when it wants to send msgs UP */ int lapdm_rll_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *ctx); @@ -34,6 +35,6 @@ void ipacc_dyn_pdch_complete(struct gsm_bts_trx_ts *ts, int rc); int rsl_tx_cbch_load_indication(struct gsm_bts *bts, bool ext_cbch, bool overflow, uint8_t amount); -int rsl_tx_meas_res(struct gsm_lchan *lchan, uint8_t *l3, int l3_len, const struct lapdm_entity *le); +int rsl_tx_meas_res(struct gsm_lchan *lchan, const uint8_t *l3, unsigned int l3_len, int timing_offset); #endif // _RSL_H */ diff --git a/include/osmo-bts/rtp_input_preen.h b/include/osmo-bts/rtp_input_preen.h new file mode 100644 index 00000000..744ae2a9 --- /dev/null +++ b/include/osmo-bts/rtp_input_preen.h @@ -0,0 +1,20 @@ +/* + * RTP input validation function: makes the accept-or-drop decision, + * and for some codecs signals additional required actions such as + * dropping one header octet. + */ + +#pragma once + +#include <stdint.h> +#include <osmo-bts/lchan.h> + +enum pl_input_decision { + PL_DECISION_DROP, + PL_DECISION_ACCEPT, + PL_DECISION_STRIP_HDR_OCTET, +}; + +enum pl_input_decision +rtp_payload_input_preen(struct gsm_lchan *lchan, const uint8_t *rtp_pl, + unsigned rtp_pl_len, bool *rfc5993_sid_flag); diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h index 80a260fe..aea55959 100644 --- a/include/osmo-bts/scheduler.h +++ b/include/osmo-bts/scheduler.h @@ -5,13 +5,6 @@ #include <osmo-bts/gsm_data.h> -/* Whether a logical channel must be activated automatically */ -#define TRX_CHAN_FLAG_AUTO_ACTIVE (1 << 0) - -/* FIXME: we should actually activate 'auto-active' channels */ -#define TRX_CHAN_IS_ACTIVE(state, chan) \ - (trx_chan_desc[chan].flags & TRX_CHAN_FLAG_AUTO_ACTIVE || (state)->active) - #define TRX_GMSK_NB_TSC(br) \ _sched_train_seq_gmsk_nb[(br)->tsc_set][(br)->tsc] @@ -80,6 +73,7 @@ enum trx_mod_type { /* A set of measurements belonging to one Uplink burst */ struct l1sched_meas_set { + uint32_t fn; /* TDMA frame number */ int16_t toa256; /* Timing of Arrival (1/256 of a symbol) */ int16_t ci_cb; /* Carrier-to-Interference (cB) */ float rssi; /* RSSI (dBm) */ @@ -96,13 +90,12 @@ struct l1sched_chan_state { bool active; /* Channel is active */ ubit_t *dl_bursts; /* burst buffer for TX */ enum trx_mod_type dl_mod_type; /* Downlink modulation type */ + uint8_t dl_mask; /* mask of transmitted bursts */ sbit_t *ul_bursts; /* burst buffer for RX */ - sbit_t *ul_bursts_prev;/* previous burst buffer for RX (repeated SACCH) */ uint32_t ul_first_fn; /* fn of first burst */ - uint8_t ul_mask; /* mask of received bursts */ + uint32_t ul_mask; /* mask of received bursts */ /* loss detection */ - uint8_t lost_frames; /* how many L2 frames were lost */ uint32_t last_tdma_fn; /* last processed TDMA frame number */ uint32_t proc_tdma_fs; /* how many TDMA frames were processed */ uint32_t lost_tdma_fs; /* how many TDMA frames were lost */ @@ -113,20 +106,19 @@ struct l1sched_chan_state { /* AMR */ uint8_t codec[4]; /* 4 possible codecs for amr */ int codecs; /* number of possible codecs */ - float ber_sum; /* sum of bit error rates */ - int ber_num; /* number of bit error rates */ + int lqual_cb_sum; /* sum of link quality samples (in cB) */ + int lqual_cb_num; /* number of link quality samples */ uint8_t ul_ft; /* current uplink FT index */ uint8_t dl_ft; /* current downlink FT index */ uint8_t ul_cmr; /* current uplink CMR index */ uint8_t dl_cmr; /* current downlink CMR index */ - uint8_t amr_loop; /* if AMR loop is enabled */ uint8_t amr_last_dtx; /* last received dtx frame type */ /* TCH/H */ uint8_t dl_ongoing_facch; /* FACCH/H on downlink */ uint8_t ul_ongoing_facch; /* FACCH/H on uplink */ - struct l1sched_meas_set meas_avg_facch; /* measurement results for last FACCH */ - uint16_t ber10k_facch; /* bit error rate for last FACCH */ + + uint8_t dl_facch_bursts; /* number of remaining DL FACCH bursts */ /* encryption */ int ul_encr_algo; /* A5/x encry algo downlink */ @@ -139,7 +131,7 @@ struct l1sched_chan_state { /* Uplink measurements */ struct { /* Active channel measurements (simple ring buffer) */ - struct l1sched_meas_set buf[8]; /* up to 8 entries */ + struct l1sched_meas_set buf[24]; /* up to 24 (BUFMAX) entries */ unsigned int current; /* current position */ /* Interference measurements */ @@ -193,6 +185,12 @@ int trx_sched_set_pchan(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config pch /*! \brief set all matching logical channels active/inactive */ int trx_sched_set_lchan(struct gsm_lchan *lchan, uint8_t chan_nr, uint8_t link_id, bool active); +/*! \brief set uplink access on given logical channels active/inactive */ +int trx_sched_set_ul_access(struct gsm_lchan *lchan, uint8_t chan_nr, bool active); + +/*! \brief set all logical channels of BCCH/CCCH active/inactive */ +int trx_sched_set_bcch_ccch(struct gsm_lchan *lchan, bool active); + /*! \brief set mode of all matching logical channels to given mode(s) */ int trx_sched_set_mode(struct gsm_bts_trx_ts *ts, uint8_t chan_nr, uint8_t rsl_cmode, uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1, @@ -231,7 +229,7 @@ struct trx_sched_multiframe { int find_sched_mframe_idx(enum gsm_phys_chan_config pchan, uint8_t tn); /*! Determine if given frame number contains SACCH (true) or other (false) burst */ -bool trx_sched_is_sacch_fn(struct gsm_bts_trx_ts *ts, uint32_t fn, bool uplink); +bool trx_sched_is_sacch_fn(const struct gsm_bts_trx_ts *ts, uint32_t fn, bool uplink); extern const struct trx_sched_multiframe trx_sched_multiframes[]; #define TRX_BI_F_NOPE_IND (1 << 0) @@ -241,6 +239,7 @@ extern const struct trx_sched_multiframe trx_sched_multiframes[]; #define TRX_BI_F_TRX_NUM (1 << 4) #define TRX_BI_F_BATCH_IND (1 << 5) #define TRX_BI_F_SHADOW_IND (1 << 6) +#define TRX_BI_F_ACCESS_BURST (1 << 7) /*! UL burst indication with the corresponding meta info */ struct trx_ul_burst_ind { @@ -272,6 +271,8 @@ struct trx_ul_burst_ind { size_t burst_len; }; +#define TRX_BR_F_FACCH (1 << 0) + /*! DL burst request with the corresponding meta info */ struct trx_dl_burst_req { uint8_t flags; /*!< see TRX_BR_F_* */ @@ -302,18 +303,24 @@ int trx_sched_ul_burst(struct l1sched_ts *l1ts, struct trx_ul_burst_ind *bi); /* Averaging mode for trx_sched_meas_avg() */ enum sched_meas_avg_mode { - /* last 4 bursts (default for xCCH, TCH/H, PTCCH and PDTCH) */ - SCHED_MEAS_AVG_M_QUAD, + /* first 22 of last 24 bursts (for TCH/F14.4, TCH/F9.6, TCH/F4.8) */ + SCHED_MEAS_AVG_M_S24N22, + /* last 22 bursts (for TCH/H4.8, TCH/H2.4) */ + SCHED_MEAS_AVG_M_S22N22, + /* last 4 bursts (default for xCCH, PTCCH and PDTCH) */ + SCHED_MEAS_AVG_M_S4N4, /* last 8 bursts (default for TCH/F and FACCH/F) */ - SCHED_MEAS_AVG_M_OCTO, + SCHED_MEAS_AVG_M_S8N8, + /* first 4 of last 6 bursts (default for TCH/H) */ + SCHED_MEAS_AVG_M_S6N4, /* last 6 bursts (default for FACCH/H) */ - SCHED_MEAS_AVG_M_SIX, + SCHED_MEAS_AVG_M_S6N6, /* first 4 of last 8 bursts */ - SCHED_MEAS_AVG_M8_FIRST_QUAD, + SCHED_MEAS_AVG_M_S8N4, /* first 2 of last 6 bursts */ - SCHED_MEAS_AVG_M6_FIRST_TWO, + SCHED_MEAS_AVG_M_S6N2, /* middle 2 of last 6 bursts */ - SCHED_MEAS_AVG_M6_MIDDLE_TWO, + SCHED_MEAS_AVG_M_S4N2, }; void trx_sched_meas_push(struct l1sched_chan_state *chan_state, @@ -321,3 +328,5 @@ void trx_sched_meas_push(struct l1sched_chan_state *chan_state, void trx_sched_meas_avg(const struct l1sched_chan_state *chan_state, struct l1sched_meas_set *avg, enum sched_meas_avg_mode mode); +uint32_t trx_sched_lookup_fn(const struct l1sched_chan_state *chan_state, + const unsigned int shift); diff --git a/include/osmo-bts/scheduler_backend.h b/include/osmo-bts/scheduler_backend.h index 50ba8228..820cca78 100644 --- a/include/osmo-bts/scheduler_backend.h +++ b/include/osmo-bts/scheduler_backend.h @@ -42,15 +42,17 @@ extern const ubit_t _sched_train_seq_gmsk_sb[64]; struct msgb *_sched_dequeue_prim(struct l1sched_ts *l1ts, const struct trx_dl_burst_req *br); int _sched_compose_ph_data_ind(struct l1sched_ts *l1ts, uint32_t fn, - enum trx_chan_type chan, uint8_t *l2, - uint8_t l2_len, float rssi, + enum trx_chan_type chan, + const uint8_t *data, size_t data_len, + uint16_t ber10k, float rssi, int16_t ta_offs_256bits, int16_t link_qual_cb, - uint16_t ber10k, enum osmo_ph_pres_info_type presence_info); int _sched_compose_tch_ind(struct l1sched_ts *l1ts, uint32_t fn, - enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len, - int16_t ta_offs_256bits, uint16_t ber10k, float rssi, + enum trx_chan_type chan, + const uint8_t *data, size_t data_len, + uint16_t ber10k, float rssi, + int16_t ta_offs_256bits, int16_t link_qual_cb, uint8_t is_sub); int tx_fcch_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br); diff --git a/include/osmo-bts/signal.h b/include/osmo-bts/signal.h index c8168a26..8359f021 100644 --- a/include/osmo-bts/signal.h +++ b/include/osmo-bts/signal.h @@ -15,4 +15,10 @@ enum signals_global { S_NEW_NSVC_ATTR, }; +struct nm_statechg_signal_data { + struct gsm_abis_mo *mo; + uint8_t old_state; + uint8_t new_state; +}; + #endif diff --git a/include/osmo-bts/ta_control.h b/include/osmo-bts/ta_control.h index 168f14a7..bf993319 100644 --- a/include/osmo-bts/ta_control.h +++ b/include/osmo-bts/ta_control.h @@ -2,4 +2,4 @@ #include <osmo-bts/gsm_data.h> -void lchan_ms_ta_ctrl(struct gsm_lchan *lchan); +void lchan_ms_ta_ctrl(struct gsm_lchan *lchan, uint8_t ms_tx_ta, int16_t toa256); diff --git a/include/osmo-bts/tx_power.h b/include/osmo-bts/tx_power.h index 8f68d8a5..73134c8b 100644 --- a/include/osmo-bts/tx_power.h +++ b/include/osmo-bts/tx_power.h @@ -77,7 +77,13 @@ int get_p_trxout_target_mdBm_lchan(const struct gsm_lchan *lchan); int get_p_trxout_actual_mdBm(const struct gsm_bts_trx *trx, uint8_t bs_power_red); int get_p_trxout_actual_mdBm_lchan(const struct gsm_lchan *lchan); -int power_ramp_start(struct gsm_bts_trx *trx, int p_total_tgt_mdBm, int bypass, ramp_compl_cb_t ramp_compl_cb); +int _power_ramp_start(struct gsm_bts_trx *trx, int p_total_tgt_mdBm, int bypass_max_power, ramp_compl_cb_t ramp_compl_cb, bool skip_ramping); +#define power_ramp_start(trx, p_total_tgt_mdBm, bypass_max_power, ramp_compl_cb) \ + _power_ramp_start(trx, p_total_tgt_mdBm, bypass_max_power, ramp_compl_cb, false) +#define power_ramp_force(trx, p_total_tgt_mdBm, bypass_max_power, ramp_compl_cb) \ + _power_ramp_start(trx, p_total_tgt_mdBm, bypass_max_power, ramp_compl_cb, true) + +void power_ramp_abort(struct gsm_bts_trx *trx); void power_trx_change_compl(struct gsm_bts_trx *trx, int p_trxout_cur_mdBm); diff --git a/include/osmo-bts/vty.h b/include/osmo-bts/vty.h index c815c85a..d326c5cd 100644 --- a/include/osmo-bts/vty.h +++ b/include/osmo-bts/vty.h @@ -12,6 +12,7 @@ enum bts_vty_node { PHY_INST_NODE, BTS_NODE, TRX_NODE, + OSMUX_NODE, }; extern struct cmd_element cfg_bts_auto_band_cmd; @@ -20,12 +21,9 @@ extern struct cmd_element cfg_bts_no_auto_band_cmd; struct phy_instance *vty_get_phy_instance(struct vty *vty, int phy_nr, int inst_nr); int bts_vty_go_parent(struct vty *vty); -int bts_vty_is_config_node(struct vty *vty, int node); int bts_vty_init(void *ctx); -struct gsm_network *gsmnet_from_vty(struct vty *v); - extern struct vty_app_info bts_vty_info; extern struct gsm_bts *g_bts; |